home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / custom.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  159KB  |  5,342 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * Custom chip emulation
  5.   *
  6.   * Copyright 1995, 1996, 1997 Bernd Schmidt
  7.   * Copyright 1995 Alessandro Bissacco
  8.   */
  9.  
  10.  /*
  11.   * This file should be split into two parts. There are two concepts of a
  12.   * "frame" here: a hardware frame which emulates the display hardware of
  13.   * the A500, and a "drawing" frame, which renders data on the screen. You
  14.   * can have multiple hardware frames for one drawing frame, or completely
  15.   * inhibit drawing while hardware frames continue to be emulated. There
  16.   * should be a separate file "drawing.c" or something.
  17.   */
  18. #include "sysconfig.h"
  19. #include "sysdeps.h"
  20.  
  21. #include <ctype.h>
  22. #include <assert.h>
  23.  
  24. #include "config.h"
  25. #include "options.h"
  26. #include "threaddep/penguin.h"
  27. #include "uae.h"
  28. #include "gensound.h"
  29. #include "sounddep/sound.h"
  30. #include "events.h"
  31. #include "memory.h"
  32. #include "custom.h"
  33. #include "readcpu.h"
  34. #include "newcpu.h"
  35. #include "cia.h"
  36. #include "disk.h"
  37. #include "blitter.h"
  38. #include "xwin.h"
  39. #include "joystick.h"
  40. #include "audio.h"
  41. #include "keybuf.h"
  42. #include "serial.h"
  43. #include "osemu.h"
  44. #include "autoconf.h"
  45. #include "picasso96.h"
  46. #include "p2c.h"
  47.  
  48. #ifdef X86_ASSEMBLY
  49. #define LORES_HACK
  50. #endif
  51. #define SPRITE_COLLISIONS
  52.  
  53. /*
  54.  * Several people have tried this define, with not much success. Turning on
  55.  * AGA garbles the screen. A place you could start looking is the calcdiw()
  56.  * function - the AGA timing parameters are different, and apparently I
  57.  * haven't figured out the correct formula yet. Pity, the current one looks
  58.  * logical.
  59.  *
  60.  * @@@ Probably won't compile in this version.
  61.  */
  62.  
  63. /* #define EMULATE_AGA */
  64.  
  65. #ifndef EMULATE_AGA
  66. #define AGA_CHIPSET 0
  67. #else
  68. #define AGA_CHIPSET 1
  69. #endif
  70.  
  71. #define SMART_UPDATE 1
  72.  
  73. #ifdef SUPPORT_PENGUINS
  74. #undef SMART_UPDATE
  75. #define SMART_UPDATE 1
  76. #endif
  77.  
  78. #if AGA_CHIPSET == 1
  79. #define MAX_PLANES 8
  80. #else
  81. #define MAX_PLANES 6
  82. #endif
  83.  
  84. /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
  85.  * on-screen. We don't emulate this. Instead, we cheat with the copper to
  86.  * compensate (much easier that way). */
  87. #define COPPER_MAGIC_FUDGE -9
  88. /* We ignore that many lores pixels at the start of the display. These are
  89.  * invisible anyway due to hardware DDF limits. */
  90. #define DISPLAY_LEFT_SHIFT 0x38
  91. static int lores_factor, lores_shift, sprite_width;
  92.  
  93. #define PIXEL_XPOS(HPOS) (((HPOS)*2 - DISPLAY_LEFT_SHIFT) << lores_shift)
  94.  
  95. /* @@@ Is maxhpos + 4 - 1 correct? (4 less isn't enough) */
  96. #define max_diwlastword (PIXEL_XPOS(maxhpos + 4 -1))
  97.  
  98. /* Mouse and joystick emulation */
  99.  
  100. #define defstepx (1<<16)
  101. #define defstepy (1<<16)
  102. #define defxoffs 0
  103. #define defyoffs 0
  104.  
  105. static const int docal = 60, xcaloff = 40, ycaloff = 20;
  106. static const int calweight = 3;
  107. static int lastsampledmx, lastsampledmy;
  108.  
  109. int buttonstate[3];
  110. int lastmx, lastmy;
  111. int newmousecounters;
  112. int ievent_alive = 0;
  113.  
  114. static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate;
  115.  
  116. static int mouse_x, mouse_y;
  117. int joy0button, joy1button;
  118. unsigned int joy0dir, joy1dir;
  119. static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
  120. static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
  121. static int sprvbfl;
  122.  
  123. /* Video buffer description structure. Filled in by the graphics system
  124.  * dependent code. */
  125.  
  126. struct vidbuf_description gfxvidinfo;
  127.  
  128. /* Events */
  129.  
  130. unsigned long int cycles, nextevent, is_lastline, did_reset;
  131. struct ev eventtab[ev_max];
  132.  
  133. frame_time_t vsynctime, vsyncmintime;
  134.  
  135. int vpos;
  136. uae_u16 lof;
  137. static int lof_changed = 0, interlace_seen = 0;
  138.  
  139. static int copper_waiting_for_blitter, copper_active;
  140. static const int dskdelay = 2; /* FIXME: ??? */
  141.  
  142. static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
  143. static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
  144.  
  145. static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
  146.  
  147. /* Big lookup tables for planar to chunky conversion. */
  148.  
  149. uae_u32 hirestab_h[256][2];
  150. uae_u32 lorestab_h[256][4];
  151.  
  152. uae_u32 hirestab_l[256][1];
  153. uae_u32 lorestab_l[256][2];
  154.  
  155. static uae_u32 sprtaba[256],sprtabb[256];
  156. static uae_u32 clxtab[256];
  157.  
  158. /* The color lookup table. */
  159.  
  160. xcolnr xcolors[4096];
  161.  
  162. /*
  163.  * Hardware registers of all sorts.
  164.  */
  165.  
  166. static int fmode;
  167.  
  168. static uae_u16 cregs[256];
  169.  
  170. uae_u16 intena,intreq;
  171. uae_u16 dmacon;
  172. uae_u16 adkcon; /* used by audio code */
  173.  
  174. static uae_u32 cop1lc,cop2lc,copcon;
  175.  
  176. /* This is but an educated guess. It seems to be correct, but this stuff
  177.  * isn't documented well. */
  178. enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop };
  179. static enum sprstate sprst[8];
  180. static int spron[8];
  181. static uaecptr sprpt[8];
  182. static int sprxpos[8], sprvstart[8], sprvstop[8];
  183.  
  184. static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat;
  185. static uae_s16 bpl1mod,bpl2mod;
  186.  
  187. static uaecptr bplpt[8];
  188. #ifndef SMART_UPDATE
  189. static char *real_bplpt[8];
  190. #endif
  191.  
  192. /*static int blitcount[256];  blitter debug */
  193.  
  194. struct color_entry {
  195. #if AGA_CHIPSET == 0
  196.     /* X86.S expects this at the start of the structure. */
  197.     xcolnr acolors[32];
  198.     uae_u16 color_regs[32];
  199. #else
  200.     uae_u32 color_regs[256];
  201. #endif
  202. };
  203.  
  204. static struct color_entry current_colors;
  205. struct color_entry colors_for_drawing;
  206. static unsigned int bplcon0,bplcon1,bplcon2,bplcon3,bplcon4;
  207. static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0;
  208. static unsigned int diwstrt,diwstop,ddfstrt,ddfstop;
  209. static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
  210. static int sprarmed[8], sprite_last_drawn_at[8];
  211. static int last_sprite_point, nr_armed;
  212. static uae_u16 clxdat, clxcon;
  213. static int clx_sprmask;
  214. static uae_u32 dskpt;
  215. static uae_u16 dsklen,dsksync;
  216.  
  217. static uae_u32 coplc;
  218. static unsigned int copi1,copi2;
  219.  
  220. static enum copper_states {
  221.     COP_stop, COP_read, COP_do_read, COP_read_ignore, COP_do_read_ignore, COP_wait, COP_morewait, COP_move, COP_skip
  222. } copstate;
  223. /* The time the copper needs for one cycle depends on bitplane DMA. Whenever
  224.  * possible, we calculate a fixed value and store it here. */
  225. static int copper_cycle_time;
  226.  
  227. static int dsklength;
  228.  
  229. static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
  230. static int diwfirstword,diwlastword;
  231. static enum { DIW_waiting_start, DIW_waiting_stop } diwstate, hdiwstate;
  232.  
  233. int dskdmaen; /* used in cia.c */
  234.  
  235. /* 880 isn't a magic number, it's a safe number with some padding at the end.
  236.  * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
  237.  * to figure out the exact space needed. */
  238. union {
  239.     /* Let's try to align this thing. */
  240.     double uupzuq;
  241.     long int cruxmedo;
  242.     unsigned char apixels[880];
  243. } pixdata;
  244.  
  245. uae_u32 ham_linebuf[880];
  246. uae_u32 aga_linebuf[880], *aga_lbufptr;
  247.  
  248. char *xlinebuffer;
  249. int next_lineno;
  250. static int nln_how;
  251.  
  252. static int *amiga2aspect_line_map, *native2amiga_line_map;
  253. static char *row_map[2049];
  254. static int max_drawn_amiga_line;
  255.  
  256. /*
  257.  * Statistics
  258.  */
  259.  
  260. /* Used also by bebox.cpp */
  261. unsigned long int msecs = 0, frametime = 0, timeframes = 0;
  262. static unsigned long int seconds_base;
  263. int bogusframe;
  264.  
  265. /*
  266.  * helper functions
  267.  */
  268.  
  269. int picasso_requested_on;
  270. int picasso_on;
  271.  
  272. uae_sem_t frame_sem, gui_sem, ihf_sem;
  273. volatile int frame_do_semup;
  274. volatile int inhibit_frame;
  275.  
  276. static int framecnt = 0;
  277. static int frame_redraw_necessary;
  278.  
  279. static __inline__ void count_frame(void)
  280. {
  281.     framecnt++;
  282.     if (framecnt >= currprefs.framerate)
  283.     framecnt = 0;
  284. }
  285.  
  286. static __inline__ void setclr(uae_u16 *p, uae_u16 val)
  287. {
  288.     if (val & 0x8000) {
  289.     *p |= val & 0x7FFF;
  290.     } else {
  291.     *p &= ~val;
  292.     }
  293. }
  294.  
  295. __inline__ int current_hpos(void)
  296. {
  297.     return cycles - eventtab[ev_hsync].oldcycles;
  298. }
  299.  
  300. static __inline__ uae_u8 *pfield_xlateptr(uaecptr plpt, int bytecount)
  301. {
  302.     if (!chipmem_bank.check(plpt,bytecount)) {
  303.     static int count = 0;
  304.     if (!count)
  305.         count++, write_log ("Warning: Bad playfield pointer\n");
  306.     return NULL;
  307.     }
  308.     return chipmem_bank.xlateaddr(plpt);
  309. }
  310.  
  311. static void calculate_copper_cycle_time (void)
  312. {
  313.     if (diwstate == DIW_waiting_start || !dmaen (DMA_BITPLANE)) {
  314.     copper_cycle_time = 2;
  315.     return;
  316.     }
  317.     copper_cycle_time = corrected_nr_planes_from_bplcon0 <= 4 ? 2 : -1;
  318. }
  319.  
  320. /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
  321. typedef void (*line_draw_func)(int, int);
  322.  
  323. #define LINE_UNDECIDED 1
  324. #define LINE_DECIDED 2
  325. #define LINE_DECIDED_DOUBLE 3
  326. #define LINE_AS_PREVIOUS 4
  327. #define LINE_BORDER_NEXT 5
  328. #define LINE_BORDER_PREV 6
  329. #define LINE_DONE 7
  330. #define LINE_DONE_AS_PREVIOUS 8
  331. #define LINE_REMEMBERED_AS_PREVIOUS 9
  332.  
  333. static char *line_drawn;
  334. static char linestate[(maxvpos + 1)*2 + 1];
  335.  
  336. static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
  337. static int linetoscr_x_adjust_bytes;
  338. static int thisframe_y_adjust, prev_y_adjust, thisframe_first_drawn_line, thisframe_last_drawn_line;
  339. static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
  340. static int extra_y_adjust;
  341.  
  342. static uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
  343.  
  344. /*
  345.  * The idea behind this code is that at some point during each horizontal
  346.  * line, we decide how to draw this line. There are many more-or-less
  347.  * independent decisions, each of which can be taken at a different horizontal
  348.  * position.
  349.  * Sprites, color changes and bitplane delay changes are handled specially:
  350.  * There isn't a single decision, but a list of structures containing
  351.  * information on how to draw the line.
  352.  */
  353.  
  354. struct color_change {
  355.     int linepos;
  356.     int regno;
  357.     unsigned long value;
  358. };
  359.  
  360. struct sprite_draw {
  361.     int linepos;
  362.     int num;
  363.     int ctl;
  364.     uae_u32 datab;
  365. };
  366.  
  367. struct delay_change {
  368.     int linepos;
  369.     unsigned int value;
  370. };
  371.  
  372. /* Way too much... */
  373. #define MAX_REG_CHANGE ((maxvpos+1) * 2 * maxhpos)
  374. static int current_change_set;
  375.  
  376. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  377. /* sam: Those arrays uses around 7Mb of BSS... That seems  */
  378. /* too much for AmigaDOS (uae crashes as soon as one loads */
  379. /* it. So I use a different strategy here (realloc the     */
  380. /* arrays when needed. That strategy might be usefull for  */
  381. /* computer with low memory.                               */
  382. static struct sprite_draw  *sprite_positions[2];
  383. static int max_sprite_draw    = 400;
  384. static int delta_sprite_draw  = 0;
  385. static struct color_change *color_changes[2];
  386. static int max_color_change   = 400;
  387. static int delta_color_change = 0;
  388. static struct delay_change *delay_changes;
  389. static int max_delay_change = 100;
  390. static int delta_delay_change = 0;
  391. #else
  392. static struct sprite_draw sprite_positions[2][MAX_REG_CHANGE];
  393. static struct color_change color_changes[2][MAX_REG_CHANGE];
  394. /* We don't remember those across frames, that would be too much effort.
  395.  * We simply redraw the line whenever we see one of these. */
  396. static struct delay_change delay_changes[MAX_REG_CHANGE];
  397. #endif
  398. static struct sprite_draw *curr_sprite_positions, *prev_sprite_positions;
  399. static struct color_change *curr_color_changes, *prev_color_changes;
  400.  
  401. static int next_color_change, next_sprite_draw, next_delay_change;
  402.  
  403. static struct color_entry color_tables[2][(maxvpos+1) * 2];
  404. static struct color_entry *curr_color_tables, *prev_color_tables;
  405. static int next_color_entry, remembered_color_entry, drawing_color_matches;
  406. static enum { color_match_acolors, color_match_full } color_match_type;
  407. static int color_src_match, color_dest_match, color_compare_result;
  408.  
  409. static int last_redraw_point;
  410.  
  411. static int first_drawn_line, last_drawn_line;
  412. static int first_block_line, last_block_line;
  413.  
  414. static __inline__ void docols(struct color_entry *colentry)
  415. {
  416. #if AGA_CHIPSET == 0
  417.     int i;
  418.     for (i = 0; i < 32; i++) {
  419.     int v = colentry->color_regs[i];
  420.     if (v < 0 || v > 4095)
  421.       continue;
  422.     colentry->acolors[i] = xcolors[v];
  423.     }
  424. #endif
  425. }
  426.  
  427. void notice_new_xcolors (void)
  428. {
  429.     int i;
  430.  
  431.     docols(¤t_colors);
  432.     docols(&colors_for_drawing);
  433.     for (i = 0; i < (maxvpos+1)*2; i++) {
  434.     docols(color_tables[0]+i);
  435.     docols(color_tables[1]+i);
  436.     }
  437. }
  438.  
  439. void notice_screen_contents_lost (void)
  440. {
  441.     frame_redraw_necessary = 2;
  442. }
  443.  
  444. static void init_regchanges (void)
  445. {
  446.     size_t i;
  447.  
  448.     next_color_change = 0;
  449.     next_sprite_draw = 0;
  450.     current_change_set = 0;
  451.     for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
  452.     linestate[i] = LINE_UNDECIDED;
  453. }
  454.  
  455. /* struct decision contains things we save across drawing frames for
  456.  * comparison (smart update stuff). */
  457. struct decision {
  458.     unsigned long color0;
  459.     int which;
  460.     int plfstrt, plflinelen;
  461.     int diwfirstword, diwlastword;
  462.     int ctable;
  463.  
  464.     uae_u16 bplcon0, bplcon1, bplcon2;
  465. #if 0 /* We don't need this. */
  466.     uae_u16 bplcon3;
  467. #endif
  468. #if AGA_CHIPSET == 1
  469.     uae_u16 bplcon4;
  470. #endif
  471. };
  472.  
  473. /* Anything related to changes in hw registers during the DDF for one
  474.  * line. */
  475. struct draw_info {
  476.     int first_sprite_draw, last_sprite_draw;
  477.     int first_color_change, last_color_change;
  478.     int first_delay_change, last_delay_change;
  479.     int nr_color_changes, nr_sprites;
  480. };
  481.  
  482. /* These few are only needed during/at the end of the scanline, and don't
  483.  * have to be remembered. */
  484. static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes, decided_hires;
  485.  
  486. /* These are generated by the drawing code from the line_decisions array for
  487.  * each line that needs to be drawn. */
  488. static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
  489. static int bpldelay1, bpldelay2;
  490. static int plfpri[3];
  491.  
  492. static struct decision line_decisions[2 * (maxvpos+1) + 1];
  493. static struct draw_info line_drawinfo[2][2 * (maxvpos+1) + 1];
  494. static struct draw_info *curr_drawinfo, *prev_drawinfo;
  495. static struct decision *dp_for_drawing;
  496. static struct draw_info *dip_for_drawing;
  497.  
  498. static char line_changed[2 * (maxvpos+1)];
  499.  
  500. #ifdef SMART_UPDATE
  501. #define MARK_LINE_CHANGED(l) do { line_changed[l] = 1; } while (0)
  502. #else
  503. #define MARK_LINE_CHANGED(l) do { } while (0)
  504. #endif
  505.  
  506. static struct decision thisline_decision;
  507. static int modulos_added, plane_decided, color_decided, very_broken_program;
  508.  
  509. static void do_sprites(int currvp, int currhp);
  510.  
  511. static void remember_ctable (void)
  512. {
  513.     if (remembered_color_entry == -1) {
  514.     /* The colors changed since we last recorded a color map. Record a
  515.      * new one. */
  516.     memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors);
  517.     remembered_color_entry = next_color_entry++;
  518.     }
  519.     thisline_decision.ctable = remembered_color_entry;
  520.     if (color_src_match == -1 || color_dest_match != remembered_color_entry
  521.     || line_decisions[next_lineno].ctable != color_src_match)
  522.     {
  523.     /* The remembered comparison didn't help us - need to compare again. */
  524.     int oldctable = line_decisions[next_lineno].ctable;
  525.     int changed = 0;
  526.  
  527.     if (oldctable == -1) {
  528.         changed = 1;
  529.         color_src_match = color_dest_match = -1;
  530.     } else {
  531.         color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs,
  532.                        ¤t_colors.color_regs,
  533.                        sizeof current_colors.color_regs) != 0;
  534.         if (color_compare_result)
  535.         changed = 1;
  536.         color_src_match = oldctable;
  537.         color_dest_match = remembered_color_entry;
  538.     }
  539.     if (changed) {
  540.         line_changed[next_lineno] = 1;
  541.     }
  542.     } else {
  543.     /* We know the result of the comparison */
  544.     if (color_compare_result)
  545.         line_changed[next_lineno] = 1;
  546.     }
  547. }
  548.  
  549. static void remember_ctable_for_border (void)
  550. {
  551.     remember_ctable ();
  552. #if 0
  553.     if (remembered_color_entry == -1) {
  554.     /* The colors changed since we last recorded a color map. Record a
  555.      * new one. */
  556.     memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors);
  557.     remembered_color_entry = next_color_entry++;
  558.     }
  559.     thisline_decision.ctable = remembered_color_entry;
  560.     if (color_src_match == -1 || color_dest_match != remembered_color_entry
  561.     || line_decisions[next_lineno].ctable != color_src_match)
  562.     {
  563.     /* The remembered comparison didn't help us - need to compare again. */
  564.     int oldctable = line_decisions[next_lineno].ctable;
  565.     int changed = 0;
  566.  
  567.     if (oldctable == -1) {
  568.         changed = 1;
  569.         color_src_match = color_dest_match = -1;
  570.     } else {
  571.         color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs,
  572.                        ¤t_colors.color_regs,
  573.                        sizeof current_colors.color_regs) != 0;
  574.         if (color_compare_result)
  575.         changed = 1;
  576.         color_src_match = oldctable;
  577.         color_dest_match = remembered_color_entry;
  578.     }
  579.     if (changed) {
  580.         line_changed[next_lineno] = 1;
  581.     }
  582.     } else {
  583.     /* We know the result of the comparison */
  584.     if (color_compare_result)
  585.         line_changed[next_lineno] = 1;
  586.     }
  587. #endif
  588. }
  589.  
  590. /* Called to determine the state of the horizontal display window state
  591.  * machine at the current position. It might have changed since we last
  592.  * checked.  */
  593. static void decide_diw (void)
  594. {
  595.     if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
  596.     && PIXEL_XPOS (current_hpos ()) >= diwfirstword)
  597.     {
  598.     thisline_decision.diwfirstword = diwfirstword;
  599.     hdiwstate = DIW_waiting_stop;
  600.     /* Decide playfield delays only at DIW start, because they don't matter before and
  601.      * some programs change them after DDF start but before DIW start. */
  602.     thisline_decision.bplcon1 = bplcon1;
  603.     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
  604.         MARK_LINE_CHANGED (next_lineno);
  605.     thisline_decision.diwlastword = -1;
  606.     }
  607.     if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
  608.     && PIXEL_XPOS (current_hpos ()) >= diwlastword)
  609.     {
  610.     thisline_decision.diwlastword = diwlastword;
  611.     hdiwstate = DIW_waiting_start;
  612.     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
  613.         MARK_LINE_CHANGED (next_lineno);
  614.     }
  615. }
  616.  
  617. /* Called when we know that the line is not in the border and we want to it.
  618.  * The data fetch starting position and length are passed as parameters. */
  619. static __inline__ void decide_as_playfield (int startpos, int len)
  620. {
  621.     thisline_decision.which = 1;
  622.  
  623.     /* The latter condition might be able to happen in interlaced frames. */
  624.     if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
  625.     thisframe_first_drawn_line = vpos;
  626.     thisframe_last_drawn_line = vpos;
  627.  
  628.     thisline_decision.plfstrt = startpos;
  629.     thisline_decision.plflinelen = len;
  630.  
  631.     /* These are for comparison. */
  632.     thisline_decision.bplcon0 = bplcon0;
  633.     thisline_decision.bplcon2 = bplcon2;
  634. #if AGA_CHIPSET == 1
  635.     thisline_decision.bplcon4 = bplcon4;
  636. #endif
  637.  
  638. #ifdef SMART_UPDATE
  639.     if (line_decisions[next_lineno].plfstrt != thisline_decision.plfstrt
  640.     || line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
  641.     || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
  642.     || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
  643. #if AGA_CHIPSET == 1
  644.     || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
  645. #endif
  646.     )
  647. #endif /* SMART_UPDATE */
  648.     line_changed[next_lineno] = 1;
  649. }
  650.  
  651. /* Called when we already decided whether the line is playfield or border,
  652.  * but are no longer sure that this was such a good idea. This can make a
  653.  * difference only for very badly written software. */
  654. static __inline__ void post_decide_line (void)
  655. {
  656.     static int warned = 0;
  657.     int tmp;
  658.  
  659.     if (thisline_decision.which == 1 && current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen
  660.     && ((bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE)))
  661.     {
  662.     /* This is getting gross... */
  663.     thisline_decision.plflinelen = current_hpos() - thisline_decision.plfstrt;
  664.     thisline_decision.plflinelen &= 7;
  665.     if (thisline_decision.plflinelen == 0)
  666.         thisline_decision.which = -1;
  667.     /* ... especially THIS! */
  668.     modulos_added = 1;
  669.     return;
  670.     }
  671.  
  672.     if (thisline_decision.which != -1 || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0
  673.     || !dmaen (DMA_BITPLANE) || current_hpos () >= thisline_decision.plfstrt + thisline_decision.plflinelen)
  674.     return;
  675. #if 0 /* Can't warn because Kickstart 1.3 does it at reset time ;-) */
  676.     if (!warned) {
  677.     write_log ("That program you are running is _really_ broken.\n");
  678.     warned = 1;
  679.     }
  680. #endif
  681.  
  682.     decided_hires = (bplcon0 & 0x8000) == 0x8000;
  683.     decided_nr_planes = nr_planes_from_bplcon0;
  684.  
  685.     /* Magic 12, Ray of Hope 2 demo does ugly things. Looks great from the
  686.      * outside, rotten inside. */
  687.     if (decided_hires) {
  688.     tmp = current_hpos () & ~3;
  689.     very_broken_program = current_hpos () & 3;
  690.     } else {
  691.     tmp = current_hpos () & ~7;
  692.     very_broken_program = current_hpos () & 7;
  693.     }
  694.     MARK_LINE_CHANGED (next_lineno); /* Play safe. */
  695.     decide_as_playfield (tmp, plflinelen + plfstrt - tmp);
  696. }
  697.  
  698. static void decide_line_1 (void)
  699. {
  700.     do_sprites(vpos, current_hpos ());
  701.  
  702.     /* Surprisingly enough, this seems to be correct here - putting this into
  703.      * decide_diw() results in garbage. */
  704.     if (diwstate == DIW_waiting_start && vpos == plffirstline) {
  705.     diwstate = DIW_waiting_stop;
  706.     calculate_copper_cycle_time ();
  707.     }
  708.     if (diwstate == DIW_waiting_stop && vpos == plflastline) {
  709.     diwstate = DIW_waiting_start;
  710.     calculate_copper_cycle_time ();
  711.     }
  712.  
  713.     if (framecnt != 0) {
  714. /*    thisline_decision.which = -2; This doesn't do anything but hurt, I think. */
  715.     return;
  716.     }
  717.  
  718.     if (!dmaen(DMA_BITPLANE) || diwstate == DIW_waiting_start || nr_planes_from_bplcon0 == 0) {
  719.     /* We don't want to draw this one. */
  720.     thisline_decision.which = -1;
  721.     thisline_decision.plfstrt = plfstrt;
  722.     thisline_decision.plflinelen = plflinelen;
  723.     return;
  724.     }
  725.  
  726.     decided_hires = (bplcon0 & 0x8000) == 0x8000;
  727.     decided_nr_planes = nr_planes_from_bplcon0;
  728. #if 0
  729.     /* The blitter gets slower if there's high bitplane activity.
  730.      * @@@ but the values must be different. FIXME */
  731.     if (bltstate != BLT_done
  732.     && ((decided_hires && decided_nr_planes > 2)
  733.         || (!decided_hires && decided_nr_planes > 4)))
  734.     {
  735.     int pl = decided_nr_planes;
  736.     unsigned int n = (eventtab[ev_blitter].evtime-cycles);
  737.     if (n > plflinelen)
  738.         n = plflinelen;
  739.     n >>= 1;
  740.     if (decided_hires)
  741.         pl <<= 1;
  742.     if (pl == 8)
  743.         eventtab[ev_blitter].evtime += plflinelen;
  744.     else if (pl == 6)
  745.         eventtab[ev_blitter].evtime += n*2;
  746.     else if (pl == 5)
  747.         eventtab[ev_blitter].evtime += n*3/2;
  748.     events_schedule();
  749.     }
  750. #endif
  751.     decide_as_playfield (plfstrt, plflinelen);
  752. }
  753.  
  754. /* Main entry point for deciding how to draw a line. May either do
  755.  * nothing, decide the line as border, or decide the line as playfield. */
  756. static __inline__ void decide_line (void)
  757. {
  758.     if (thisline_decision.which == 0 && current_hpos() >= plfstrt)
  759.     decide_line_1 ();
  760. }
  761.  
  762. /* Called when a color is about to be changed (write to a color register),
  763.  * but the new color has not been entered into the table yet. */
  764. static void record_color_change (int regno, unsigned long value)
  765. {
  766.     /* Early positions don't appear on-screen. */
  767.     if (framecnt != 0 || vpos < minfirstline || current_hpos () < 0x18
  768.     /*|| currprefs.emul_accuracy == 0*/)
  769.     return;
  770.  
  771.     decide_diw ();
  772.     decide_line ();
  773.  
  774.     /* See if we can record the color table, but have not done so yet.
  775.      * @@@ There might be a minimal performance loss in case someone changes
  776.      * a color exactly at the start of the DIW. I don't think it can actually
  777.      * fail to work even in this case, but I'm not 100% sure.
  778.      * @@@ There might be a slightly larger performance loss if we're drawing
  779.      * this line as border... especially if there are changes in colors != 0
  780.      * we might end up setting line_changed for no reason. FIXME */
  781.     if (thisline_decision.diwfirstword >= 0
  782.     && thisline_decision.which != 0)
  783.     {
  784.     if (thisline_decision.ctable == -1)
  785.         remember_ctable ();
  786.     }
  787.  
  788.     /* Changes outside the DIW can be ignored if the modified color is not the
  789.      * background color, or if the accuracy is < 2. */
  790.     if ((regno != 0 || currprefs.emul_accuracy < 2)
  791.     && (diwstate == DIW_waiting_start || thisline_decision.diwfirstword < 0
  792.         || thisline_decision.diwlastword >= 0
  793.         || thisline_decision.which == 0
  794.         || (thisline_decision.which == 1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)))
  795.     return;
  796.  
  797.     /* If the border is changed the first time before the DIW, record the
  798.      * original starting border value. */
  799.     if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) {
  800.     thisline_decision.color0 = current_colors.color_regs[0];
  801.     if (line_decisions[next_lineno].color0 != value)
  802.         line_changed[next_lineno] = 1;
  803.     }
  804.     /* Anything else gets recorded in the color_changes table. */
  805. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  806.     if(next_color_change >= max_color_change) {
  807.     ++delta_color_change;
  808.     return;
  809.     }
  810. #endif
  811.     curr_color_changes[next_color_change].linepos = current_hpos ();
  812.     curr_color_changes[next_color_change].regno = regno;
  813.     curr_color_changes[next_color_change++].value = value;
  814. }
  815.  
  816. /* Stupid hack to get some Sanity demos working. */
  817. static void decide_delay (void)
  818. {
  819.     static int warned;
  820.  
  821.     /* Don't do anything if we're outside the DIW. */
  822.     if (thisline_decision.diwfirstword == -1 || thisline_decision.diwlastword > 0)
  823.     return;
  824.     decide_line ();
  825.     /* Half-hearted attempt to get things right even when post_decide_line() changes
  826.      * the decision afterwards. */
  827.     if (thisline_decision.which != 1) {
  828.     thisline_decision.bplcon1 = bplcon1;
  829.     return;
  830.     }
  831.     /* @@@ Could check here for DDF stopping earlier than DIW */
  832.  
  833. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  834.     if(next_delay_change >= max_delay_change) {
  835.     ++delta_delay_change;
  836.     return;
  837.     }
  838. #endif
  839.     delay_changes[next_delay_change].linepos = current_hpos ();
  840.     delay_changes[next_delay_change++].value = bplcon1;
  841.     if (!warned) {
  842.     warned = 1;
  843.     write_log ("Program is torturing BPLCON1.\n");
  844.     }
  845. }
  846.  
  847. /*
  848.  * The decision which bitplane pointers to use is not taken at plfstrt, since
  849.  * data fetch does not start for all planes at this point. Therefore, we wait
  850.  * for the end of the ddf area or the first write to any of the bitplane
  851.  * pointer registers, whichever comes last, before we decide which plane pointers
  852.  * to use.
  853.  * Call decide_line() before this function.
  854.  */
  855. static void decide_plane (void)
  856. {
  857.     int i, bytecount;
  858.  
  859.     if (framecnt != 0 || plane_decided)
  860.     return;
  861.  
  862.     if (decided_nr_planes == -1 /* Still undecided */
  863.     || current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen)
  864.     return;
  865.  
  866.     plane_decided = 1;
  867.  
  868.     bytecount = plflinelen / (decided_hires ? 4 : 8) * 2;
  869.  
  870.     if (bytecount > MAX_WORDS_PER_LINE * 2) {
  871.     /* Can't happen. */
  872.     static int warned = 0;
  873.     if (!warned)
  874.         write_log ("Mysterious bug in decide_plane(). Please report.\n");
  875.     bytecount = 0;
  876.     }
  877.     if (!very_broken_program) {
  878.     uae_u8 *dataptr = line_data[next_lineno];
  879.     for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
  880.         uaecptr pt = bplpt[i];
  881.         uae_u8 *real_ptr = pfield_xlateptr(pt, bytecount);
  882.         if (real_ptr == NULL)
  883.         real_ptr = pfield_xlateptr(0, 0);
  884. #ifdef SMART_UPDATE
  885. #if 1
  886.         if (line_changed[next_lineno])
  887.         memcpy (dataptr, real_ptr, bytecount);
  888.         else
  889. #endif
  890.         line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
  891. #else
  892.         real_bplpt[i] = real_ptr;
  893. #endif
  894.     }
  895.     } else {
  896.     uae_u8 *dataptr = line_data[next_lineno];
  897.     for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
  898.         uaecptr pt = bplpt[i];
  899.         uae_u8 *real_ptr;
  900.  
  901.         if (decided_hires) {
  902.         switch (i) {
  903.          case 3: pt -= 2;
  904.          case 2: pt -= (very_broken_program >= 3 ? 2 : 0); break;
  905.          case 1: pt -= (very_broken_program >= 2 ? 2 : 0); break;
  906.          case 0: break;
  907.         }
  908.         } else {
  909.         switch (i) {
  910.          case 5: pt -= (very_broken_program >= 3 ? 2 : 0); break;
  911.          case 4: pt -= (very_broken_program >= 7 ? 2 : 0); break;
  912.          case 3: pt -= (very_broken_program >= 2 ? 2 : 0); break;
  913.          case 2: pt -= (very_broken_program >= 6 ? 2 : 0); break;
  914.          case 1: pt -= (very_broken_program >= 4 ? 2 : 0); break;
  915.          case 0: break;
  916.         }
  917.         }
  918.         real_ptr = pfield_xlateptr(pt, bytecount);
  919.         if (real_ptr == NULL)
  920.         real_ptr = pfield_xlateptr(0, 0);
  921. #ifdef SMART_UPDATE
  922.         if (!line_changed[next_lineno])
  923.         line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
  924.         else
  925.         memcpy (dataptr, real_ptr, bytecount);
  926. #else
  927.         real_bplpt[i] = real_ptr;
  928. #endif
  929.     }
  930.     }
  931. }
  932.  
  933. /*
  934.  * Called from the BPLxMOD routines, after a new value has been written.
  935.  * This routine decides whether the new value is already relevant for the
  936.  * current line.
  937.  */
  938. static void decide_modulos (void)
  939. {
  940.     /* All this effort just for the Sanity WOC demo... */
  941.     decide_line ();
  942.     if (decided_nr_planes != -1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
  943.     return;
  944.     decided_bpl1mod = bpl1mod;
  945.     decided_bpl2mod = bpl2mod;
  946. }
  947.  
  948. /*
  949.  * Add the modulos to the bitplane pointers if data fetch is already
  950.  * finished for the current line.
  951.  * Call decide_plane() before calling this, so that we won't use the
  952.  * new values of the plane pointers for the current line.
  953.  */
  954. static void do_modulos (void)
  955. {
  956.     /* decided_nr_planes is != -1 if this line should be drawn by the
  957.      * display hardware, regardless of whether it fits on the emulated screen.
  958.      */
  959.     if (decided_nr_planes != -1 && plane_decided && !modulos_added
  960.     && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
  961.     {
  962.     int bytecount = thisline_decision.plflinelen / (decided_hires ? 4 : 8) * 2;
  963.     int add1 = bytecount + decided_bpl1mod;
  964.     int add2 = bytecount + decided_bpl2mod;
  965.  
  966.     if (!very_broken_program) {
  967.         switch (decided_nr_planes) {
  968.          case 8: bplpt[7] += add2;
  969.          case 7: bplpt[6] += add1;
  970.          case 6: bplpt[5] += add2;
  971.          case 5: bplpt[4] += add1;
  972.          case 4: bplpt[3] += add2;
  973.          case 3: bplpt[2] += add1;
  974.          case 2: bplpt[1] += add2;
  975.          case 1: bplpt[0] += add1;
  976.         }
  977.     } else if (bplhires) {
  978.         switch (decided_nr_planes) {
  979.          case 8: bplpt[7] += add2;
  980.          case 7: bplpt[6] += add1;
  981.          case 6: bplpt[5] += add2;
  982.          case 5: bplpt[4] += add1;
  983.          case 4: bplpt[3] += add2 - 2;
  984.          case 3: bplpt[2] += add1 - (very_broken_program >= 3 ? 2 : 0);
  985.          case 2: bplpt[1] += add2 - (very_broken_program >= 2 ? 2 : 0);
  986.          case 1: bplpt[0] += add1;
  987.         }
  988.     } else {
  989.         switch (decided_nr_planes) {
  990.          case 8: bplpt[7] += add2;
  991.          case 7: bplpt[6] += add1;
  992.          case 6: bplpt[5] += add2 - (very_broken_program >= 3 ? 2 : 0);
  993.          case 5: bplpt[4] += add1 - (very_broken_program >= 7 ? 2 : 0);
  994.          case 4: bplpt[3] += add2 - (very_broken_program >= 2 ? 2 : 0);
  995.          case 3: bplpt[2] += add1 - (very_broken_program >= 6 ? 2 : 0);
  996.          case 2: bplpt[1] += add2 - (very_broken_program >= 4 ? 2 : 0);
  997.          case 1: bplpt[0] += add1;
  998.         }
  999.     }
  1000.  
  1001.     modulos_added = 1;
  1002.     }
  1003. }
  1004.  
  1005. static __inline__ void record_sprite (int spr, int sprxp)
  1006. {
  1007.     int pos = next_sprite_draw;
  1008.     unsigned int data, datb;
  1009.  
  1010. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  1011.     if(pos >= max_sprite_draw) {
  1012.     ++delta_sprite_draw;
  1013.     return;
  1014.     }
  1015. #endif
  1016.     data = sprdata[spr];
  1017.     datb = sprdatb[spr];
  1018.  
  1019.     /* XXX FIXME, this isn't very clever, but it might do */
  1020.     for (;;) {
  1021.     if (pos == curr_drawinfo[next_lineno].first_sprite_draw)
  1022.         break;
  1023.     if (curr_sprite_positions[pos-1].linepos < sprxp)
  1024.         break;
  1025.     if (curr_sprite_positions[pos-1].linepos == sprxp
  1026.         && curr_sprite_positions[pos-1].num > spr)
  1027.         break;
  1028.     printf("Foo\n");
  1029.     pos--;
  1030.     }
  1031.     if (pos != next_sprite_draw) {
  1032.     int pos2 = next_sprite_draw;
  1033.     while (pos2 != pos) {
  1034.         curr_sprite_positions[pos2] = curr_sprite_positions[pos2-1];
  1035.         pos2--;
  1036.     }
  1037.     }
  1038.     curr_sprite_positions[pos].linepos = sprxp;
  1039.     curr_sprite_positions[pos].num = spr;
  1040.     curr_sprite_positions[pos].ctl = sprctl[spr];
  1041.     curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8]
  1042.                     | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]);
  1043.     next_sprite_draw++;
  1044. }
  1045.  
  1046. static void decide_sprites (void)
  1047. {
  1048.     int nrs[8], posns[8], count, i;
  1049.     int point = PIXEL_XPOS (current_hpos ());
  1050.  
  1051.     if (framecnt != 0 || current_hpos() < 0x14 || nr_armed == 0 || point == last_sprite_point)
  1052.     return;
  1053.  
  1054.     decide_diw ();
  1055.     decide_line ();
  1056.  
  1057.     if (thisline_decision.which != 1)
  1058.     return;
  1059.  
  1060.     count = 0;
  1061.     for (i = 0; i < 8; i++) {
  1062.     int sprxp = sprxpos[i];
  1063.     int j, bestp;
  1064.  
  1065.     if (!sprarmed[i] || sprxp < 0 || sprxp > point || last_sprite_point >= sprxp)
  1066.         continue;
  1067.     if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword)
  1068.         || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword))
  1069.         continue;
  1070.  
  1071.     for (bestp = 0; bestp < count; bestp++) {
  1072.         if (posns[bestp] > sprxp)
  1073.         break;
  1074.         if (posns[bestp] == sprxp && nrs[bestp] < i)
  1075.         break;
  1076.     }
  1077.     for (j = count; j > bestp; j--) {
  1078.         posns[j] = posns[j-1];
  1079.         nrs[j] = nrs[j-1];
  1080.     }
  1081.     posns[j] = sprxp;
  1082.     nrs[j] = i;
  1083.     count++;
  1084.     }
  1085.     for (i = 0; i < count; i++)
  1086.     record_sprite(nrs[i], posns[i]);
  1087.     last_sprite_point = point;
  1088. }
  1089.  
  1090. /* End of a horizontal scan line. Finish off all decisions that were not
  1091.  * made yet. */
  1092. static void finish_decisions (void)
  1093. {
  1094.     struct draw_info *dip;
  1095.     struct draw_info *dip_old;
  1096.     struct decision *dp;
  1097.     int changed;
  1098.  
  1099.     if (framecnt != 0)
  1100.     return;
  1101.  
  1102.     decide_diw ();
  1103.     if (thisline_decision.which == 0)
  1104.     decide_line_1 ();
  1105.  
  1106.     /* Large DIWSTOP values can cause the stop position never to be
  1107.      * reached, so the state machine always stays in the same state and
  1108.      * there's a more-or-less full-screen DIW. */
  1109.     if (hdiwstate == DIW_waiting_stop) {
  1110.     thisline_decision.diwlastword = max_diwlastword;
  1111.     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
  1112.         MARK_LINE_CHANGED (next_lineno);
  1113.     }
  1114.  
  1115.     if (line_decisions[next_lineno].which != thisline_decision.which)
  1116.     line_changed[next_lineno] = 1;
  1117.     decide_plane ();
  1118.  
  1119.     dip = curr_drawinfo + next_lineno;
  1120.     dip_old = prev_drawinfo + next_lineno;
  1121.     dp = line_decisions + next_lineno;
  1122.     changed = line_changed[next_lineno];
  1123.  
  1124.     if (thisline_decision.which == 1) {
  1125.     if (diwlastword > max_diwstop)
  1126.         max_diwstop = diwlastword;
  1127.     if (diwfirstword < min_diwstart)
  1128.         min_diwstart = diwfirstword;
  1129.  
  1130.     decide_sprites();
  1131.  
  1132.     if (thisline_decision.bplcon1 != line_decisions[next_lineno].bplcon1)
  1133.         changed = 1;
  1134.     }
  1135.  
  1136.     dip->last_color_change = next_color_change;
  1137.     dip->last_delay_change = next_delay_change;
  1138.     dip->last_sprite_draw = next_sprite_draw;
  1139.  
  1140.     if (thisline_decision.ctable == -1) {
  1141.     if (thisline_decision.which == 1)
  1142.         remember_ctable ();
  1143.     else
  1144.         remember_ctable_for_border ();
  1145.     }
  1146.     if (thisline_decision.which == -1 && thisline_decision.color0 == 0xFFFFFFFFul)
  1147.     thisline_decision.color0 = current_colors.color_regs[0];
  1148.  
  1149.     dip->nr_color_changes = next_color_change - dip->first_color_change;
  1150.     dip->nr_sprites = next_sprite_draw - dip->first_sprite_draw;
  1151.  
  1152.     if (dip->first_delay_change != dip->last_delay_change)
  1153.     changed = 1;
  1154.     if (!changed
  1155.     && (dip->nr_color_changes != dip_old->nr_color_changes
  1156.         || (dip->nr_color_changes > 0
  1157.         && memcmp (curr_color_changes + dip->first_color_change,
  1158.                prev_color_changes + dip_old->first_color_change,
  1159.                dip->nr_color_changes * sizeof *curr_color_changes) != 0)))
  1160.     changed = 1;
  1161.     if (!changed && thisline_decision.which == 1
  1162.     && (dip->nr_sprites != dip_old->nr_sprites
  1163.         || (dip->nr_sprites > 0
  1164.         && memcmp (curr_sprite_positions + dip->first_sprite_draw,
  1165.                prev_sprite_positions + dip_old->first_sprite_draw,
  1166.                dip->nr_sprites * sizeof *curr_sprite_positions) != 0)))
  1167.     changed = 1;
  1168.  
  1169.     if (changed) {
  1170.     line_changed[next_lineno] = 1;
  1171.     *dp = thisline_decision;
  1172.     } else
  1173.     /* The only one that may differ: */
  1174.     dp->ctable = thisline_decision.ctable;
  1175. }
  1176.  
  1177. /* Set the state of all decisions to "undecided" for a new scanline. */
  1178. static void reset_decisions (void)
  1179. {
  1180.     if (framecnt != 0)
  1181.     return;
  1182.     thisline_decision.which = 0;
  1183.     decided_bpl1mod = bpl1mod;
  1184.     decided_bpl2mod = bpl2mod;
  1185.     decided_nr_planes = -1;
  1186.  
  1187.     /* decided_hires shouldn't be touched before it's initialized by decide_line(). */
  1188.     thisline_decision.diwfirstword = -1;
  1189.     thisline_decision.diwlastword = -2;
  1190.     if (hdiwstate == DIW_waiting_stop) {
  1191.     thisline_decision.diwfirstword = PIXEL_XPOS (DISPLAY_LEFT_SHIFT/2);
  1192.     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
  1193.         MARK_LINE_CHANGED (next_lineno);
  1194.     }
  1195.     thisline_decision.ctable = -1;
  1196.     thisline_decision.color0 = 0xFFFFFFFFul;
  1197.  
  1198.     line_changed[next_lineno] = 0;
  1199.     curr_drawinfo[next_lineno].first_color_change = next_color_change;
  1200.     curr_drawinfo[next_lineno].first_delay_change = next_delay_change;
  1201.     curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw;
  1202.  
  1203.     /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
  1204.     last_sprite_point = 0;
  1205.     modulos_added = 0;
  1206.     plane_decided = 0;
  1207.     color_decided = 0;
  1208.     very_broken_program = 0;
  1209. }
  1210.  
  1211. /* Initialize the decision array, once before the emulator really starts. */
  1212. static void init_decisions (void)
  1213. {
  1214.     size_t i;
  1215.     for (i = 0; i < sizeof line_decisions / sizeof *line_decisions; i++) {
  1216.     line_decisions[i].which = -2;
  1217.     }
  1218. }
  1219.  
  1220. /* Calculate display window and data fetch values from the corresponding
  1221.  * hardware registers. */
  1222. static void calcdiw (void)
  1223. {
  1224.     diwfirstword = ((diwstrt & 0xFF) - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
  1225.     diwlastword  = ((diwstop & 0xFF) + 0x100 - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
  1226.  
  1227.     if (diwlastword > max_diwlastword)
  1228.     diwlastword = max_diwlastword;
  1229.     if (diwfirstword < 0)
  1230.     diwfirstword = 0;
  1231.     if (diwlastword < 0)
  1232.     diwlastword = 0;
  1233.  
  1234.     plffirstline = diwstrt >> 8;
  1235.     plflastline = diwstop >> 8;
  1236. #if 0
  1237.     /* This happens far too often. */
  1238.     if (plffirstline < minfirstline) {
  1239.     fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
  1240.     plffirstline = minfirstline;
  1241.     }
  1242. #endif
  1243.     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
  1244. #if 0 /* Turrican does this */
  1245.     if (plflastline > 313) {
  1246.     fprintf(stderr, "Warning: Playfield out of range!\n");
  1247.     plflastline = 313;
  1248.     }
  1249. #endif
  1250.     plfstrt = ddfstrt;
  1251.     plfstop = ddfstop;
  1252.     if (plfstrt < 0x18) plfstrt = 0x18;
  1253.     if (plfstop < 0x18) plfstop = 0x18;
  1254.     if (plfstop > 0xD8) plfstop = 0xD8;
  1255.     if (plfstrt > plfstop) plfstrt = plfstop;
  1256.  
  1257.     /* ! If the masking operation is changed, the pfield_doline code could break
  1258.      * on some systems (alignment) */
  1259.     /* This actually seems to be correct now, at least the non-AGA stuff... */
  1260.     plfstrt &= ~3;
  1261.     plfstop &= ~3;
  1262.     /* @@@ Start looking for AGA bugs here... (or maybe even in the above masking ops) */
  1263.     if ((fmode & 3) == 0)
  1264.     plflinelen = (plfstop-plfstrt+15) & ~7;
  1265.     else if ((fmode & 3) == 3)
  1266.     plflinelen = (plfstop-plfstrt+63) & ~31;
  1267.     else
  1268.     plflinelen = (plfstop-plfstrt+31) & ~15;
  1269. }
  1270.  
  1271. /*
  1272.  * Screen update macros/functions
  1273.  */
  1274.  
  1275. static unsigned int ham_lastcolor;
  1276.  
  1277. static void init_ham_decoding(int first)
  1278. {
  1279.     int pix = dp_for_drawing->diwfirstword;
  1280.     ham_lastcolor = colors_for_drawing.color_regs[0];
  1281.     while (pix < first) {
  1282.     int pv = pixdata.apixels[pix];
  1283.     switch(pv & 0x30) {
  1284.      case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
  1285.      case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
  1286.      case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
  1287.      case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
  1288.     }
  1289.     pix++;
  1290.     }
  1291. }
  1292.  
  1293. static void decode_ham6 (int pix, int stoppos)
  1294. {
  1295.     uae_u32 *buf = ham_linebuf;
  1296.  
  1297.     if (!bplham || bplplanecnt != 6)
  1298.     return;
  1299.  
  1300.     if (stoppos > dp_for_drawing->diwlastword)
  1301.     stoppos = dp_for_drawing->diwlastword;
  1302.     if (pix < dp_for_drawing->diwfirstword) {
  1303.     ham_lastcolor = colors_for_drawing.color_regs[0];
  1304.     pix = dp_for_drawing->diwfirstword;
  1305.     }
  1306. #ifdef LORES_HACK
  1307.     if (currprefs.gfx_lores == 2)
  1308.     pix <<= 1, stoppos <<= 1;
  1309. #endif
  1310.     while (pix < stoppos) {
  1311.     int pv = pixdata.apixels[pix];
  1312.     switch(pv & 0x30) {
  1313.      case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
  1314.      case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
  1315.      case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
  1316.      case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
  1317.     }
  1318.  
  1319.     buf[pix++] = ham_lastcolor;
  1320.     }
  1321. }
  1322. #if 0
  1323. static void decode_ham_aga (int pix, int stoppos)
  1324. {
  1325.     static uae_u32 lastcolor;
  1326.     uae_u32 *buf = ham_linebuf;
  1327.  
  1328.     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
  1329.     return;
  1330.  
  1331.     if (pix <= dp_for_drawing->diwfirstword) {
  1332.     pix = dp_for_drawing->diwfirstword;
  1333.     lastcolor = colors_for_drawing.color_regs[0];
  1334.     }
  1335.  
  1336.     if (dp_for_drawing->bplplanecnt == 6) {
  1337.     /* HAM 6 */
  1338.     while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
  1339.         int pv = pixdata.apixels[pix];
  1340.         switch(pv & 0x30) {
  1341.          case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
  1342.          case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
  1343.          case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
  1344.          case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
  1345.         }
  1346.         buf[pix++] = lastcolor;
  1347.     }
  1348.     } else if (dp_for_drawing->bplplanecnt == 8) {
  1349.     /* HAM 8 */
  1350.     while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
  1351.         int pv = pixdata.apixels[pix];
  1352.         switch(pv & 0x3) {
  1353.          case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
  1354.          case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
  1355.          case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
  1356.          case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
  1357.         }
  1358.         buf[pix++] = lastcolor;
  1359.     }
  1360.     }
  1361. }
  1362. #endif
  1363.  
  1364. #if AGA_CHIPSET != 0
  1365. /* WARNING: Not too much of this will work correctly yet. */
  1366.  
  1367. static void pfield_linetoscr_aga(int pix, int stoppos)
  1368. {
  1369.     uae_u32 *buf = aga_lbufptr;
  1370.     int i;
  1371.     int xor = (uae_u8)(bplcon4 >> 8);
  1372.     int oldpix = pix; \
  1373.  
  1374.     buf -= pix; \
  1375.  
  1376.     for (i = 0; i < stoppos; i++)
  1377.     pixdata.apixels[i] ^= xor;
  1378.  
  1379.     while (pix < diwfirstword && pix < stoppos) {
  1380.     buf[pix++] = colors_for_drawing.color_regs[0];
  1381.     }
  1382.     if (bplham) {
  1383.     while (pix < diwlastword && pix < stoppos) {
  1384.         uae_u32 d = ham_linebuf[pix];
  1385.         buf[pix] = d;
  1386.         pix++;
  1387.     }
  1388.     } else if (bpldualpf) {
  1389.     /* Dual playfield */
  1390.     int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
  1391.     int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
  1392.     while (pix < diwlastword && pix < stoppos) {
  1393.         int pixcol = pixdata.apixels[pix];
  1394.         int pfno = lookup_no[pixcol];
  1395.  
  1396.         if (spixstate[pix]) {
  1397.         buf[pix] = colors_for_drawing.color_regs[pixcol];
  1398.         } else {
  1399.         int val = lookup[pixdata.apixels[pix]];
  1400.         if (pfno == 2)
  1401.             val += dblpfofs[(bplcon2 >> 10) & 7];
  1402.         buf[pix] = colors_for_drawing.color_regs[val];
  1403.         }
  1404.         pix++;
  1405.     }
  1406.     } else if (bplehb) {
  1407.     while (pix < diwlastword && pix < stoppos) {
  1408.         int pixcol = pixdata.apixels[pix];
  1409.         uae_u32 d = colors_for_drawing.color_regs[pixcol];
  1410.         /* What about sprites? */
  1411.         if (pixcol & 0x20)
  1412.         d = (d & 0x777777) >> 1;
  1413.         buf[pix] = d;
  1414.         pix++;
  1415.     }
  1416.     } else {
  1417.     while (pix < diwlastword && pix < stoppos) {
  1418.         int pixcol = pixdata.apixels[pix];
  1419.         buf[pix] = colors_for_drawing.color_regs[pixcol];
  1420.         pix++;
  1421.     }
  1422.     }
  1423.     while (pix < stoppos) {
  1424.     buf[pix++] = colors_for_drawing.color_regs[0];
  1425.     }
  1426.     aga_lbufptr += pix - oldpix;
  1427. }
  1428.  
  1429. static void aga_translate32(int start, int stop)
  1430. {
  1431.     memcpy (((uae_u32 *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start));
  1432. }
  1433.  
  1434. static void aga_translate16(int start, int stop)
  1435. {
  1436.     int i;
  1437.     for (i = start; i < stop; i++) {
  1438.     uae_u32 d = aga_linebuf[i];
  1439.     uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
  1440.     ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
  1441.     }
  1442. }
  1443.  
  1444. static void aga_translate8(int start, int stop)
  1445. {
  1446.     int i;
  1447.     for (i = start; i < stop; i++) {
  1448.     uae_u32 d = aga_linebuf[i];
  1449.     uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
  1450.     ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
  1451.     }
  1452. }
  1453. #endif
  1454.  
  1455. static int linetoscr_double_offset;
  1456.  
  1457. #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \
  1458. static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
  1459. { \
  1460.     TYPE *buf = ((TYPE *)xlinebuffer); \
  1461.     int oldpix = pix; \
  1462.     /* These are different for register-allocation purposes. */ \
  1463.     TYPE d1, d2; \
  1464.     int offset; \
  1465. \
  1466.     if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
  1467. \
  1468.     d1 = CONVERT(colors_for_drawing.acolors[0]); \
  1469.     while (pix < lframe_end) { \
  1470.     buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
  1471.     pix++; \
  1472.     } \
  1473.     if (bplham && bplplanecnt == 6) { \
  1474.     /* HAM 6 */ \
  1475.     while (pix < diw_end) { \
  1476.         TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \
  1477.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1478.         pix++; \
  1479.     } \
  1480.     } else if (bpldualpf) { \
  1481.     /* Dual playfield */ \
  1482.     int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
  1483.     while (pix < diw_end) { \
  1484.         int pixcol = pixdata.apixels[pix]; \
  1485.         TYPE d; \
  1486.         d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \
  1487.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1488.         pix++; \
  1489.     } \
  1490.     } else if (bplehb) { \
  1491.     while (pix < diw_end) { \
  1492.         int p = pixdata.apixels[pix]; \
  1493.         TYPE d = CONVERT (colors_for_drawing.acolors[p]); \
  1494.         if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \
  1495.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1496.         pix++; \
  1497.     } \
  1498.     } else { \
  1499.     while (pix < diw_end) { \
  1500.         TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \
  1501.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1502.         pix++; \
  1503.     } \
  1504.     } \
  1505.     d2 = CONVERT (colors_for_drawing.acolors[0]); \
  1506.     while (pix < stoppos) { \
  1507.     buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
  1508.     pix++; \
  1509.     } \
  1510. }
  1511.  
  1512. #define FILL_LINE(NAME, TYPE, CONVERT) \
  1513. static void NAME(char *buf, int start, int stop) \
  1514. { \
  1515.     TYPE *b = (TYPE *)buf; \
  1516.     int i;\
  1517.     xcolnr col = colors_for_drawing.acolors[0]; \
  1518.     for (i = start; i < stop; i++) \
  1519.     b[i] = CONVERT (col); \
  1520. }
  1521.  
  1522. LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,)
  1523. LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,)
  1524. LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,)
  1525. LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,)
  1526. LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,)
  1527. LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,)
  1528.  
  1529. FILL_LINE(fill_line_8, uae_u8,)
  1530. FILL_LINE(fill_line_16, uae_u16,)
  1531. FILL_LINE(fill_line_32, uae_u32,)
  1532.  
  1533. #ifdef HAVE_UAE_U24
  1534. LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert)
  1535. LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert)
  1536. FILL_LINE(fill_line_24, uae_u24, uae24_convert)
  1537. #else
  1538. /* Dummy versions */
  1539. static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos)
  1540. {
  1541. }
  1542. static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos)
  1543. {
  1544. }
  1545. static void fill_line_24 (char *buf, int start, int stop)
  1546. {
  1547. }
  1548. #endif
  1549.  
  1550. static __inline__ void fill_line_full (void)
  1551. {
  1552.     switch (gfxvidinfo.pixbytes) {
  1553.      case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
  1554.      case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
  1555.      case 3: fill_line_24(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
  1556.      case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
  1557.     }
  1558. }
  1559.  
  1560. #define fill_line fill_line_full
  1561.  
  1562. #define pfield_linetoscr_full8 pfield_linetoscr_8
  1563. #define pfield_linetoscr_full16 pfield_linetoscr_16
  1564. #define pfield_linetoscr_full24 pfield_linetoscr_24
  1565. #define pfield_linetoscr_full32 pfield_linetoscr_32
  1566.  
  1567. #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
  1568. #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
  1569. #define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow
  1570. #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
  1571.  
  1572. #if 1 && defined(X86_ASSEMBLY)
  1573. /* This version of fill_line is probably a win on all machines, but for
  1574.  * now I'm cautious */
  1575. #undef fill_line
  1576. static __inline__ void fill_line (void)
  1577. {
  1578.     int shift;
  1579.     int nints, nrem;
  1580.     int *start;
  1581.     xcolnr val;
  1582.  
  1583. #ifdef HAVE_UAE_U24
  1584.     if (gfxvidinfo.pixbytes == 3) {
  1585.     fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
  1586.     return;
  1587.     }
  1588. #endif
  1589.     
  1590.     shift = 0;
  1591.     if (gfxvidinfo.pixbytes == 2)
  1592.     shift = 1;
  1593.     if (gfxvidinfo.pixbytes == 4)
  1594.     shift = 2;
  1595.  
  1596.     nints = gfxvidinfo.width >> (2-shift);
  1597.     nrem = nints & 7;
  1598.     nints &= ~7;
  1599.     start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
  1600.     val = colors_for_drawing.acolors[0];
  1601.     for (; nints > 0; nints -= 8, start+=8) {
  1602.     *start = val;
  1603.     *(start+1) = val;
  1604.     *(start+2) = val;
  1605.     *(start+3) = val;
  1606.     *(start+4) = val;
  1607.     *(start+5) = val;
  1608.     *(start+6) = val;
  1609.     *(start+7) = val;
  1610.     }
  1611.  
  1612.     switch (nrem) {
  1613.      case 7:
  1614.     *start++ = val;
  1615.      case 6:
  1616.     *start++ = val;
  1617.      case 5:
  1618.     *start++ = val;
  1619.      case 4:
  1620.     *start++ = val;
  1621.      case 3:
  1622.     *start++ = val;
  1623.      case 2:
  1624.     *start++ = val;
  1625.      case 1:
  1626.     *start = val;
  1627.     }
  1628. }
  1629.  
  1630. #undef pfield_linetoscr_full8
  1631. /* The types are lies, of course. */
  1632. extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8");
  1633. extern void pfield_linetoscr_ehb_asm8(void) __asm__("pfield_linetoscr_ehb_asm8");
  1634. extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8");
  1635. extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8");
  1636. extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8");
  1637. extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
  1638. extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
  1639. extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
  1640.  
  1641. static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos)
  1642. {
  1643.     int lframe_end_1, diw_end_1;
  1644.  
  1645.     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
  1646.     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
  1647.  
  1648.     if (bplham && bplplanecnt == 6) {
  1649.     pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1650.     } else if (bpldualpf) {
  1651. #ifdef LORES_HACK
  1652.     if (currprefs.gfx_lores == 2)
  1653.         pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
  1654.                    bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1655.     else
  1656. #endif
  1657.         pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
  1658.                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1659.     } else if (bplehb) {
  1660. #ifdef LORES_HACK
  1661.     if (currprefs.gfx_lores == 2)
  1662.         pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1663.     else
  1664. #endif
  1665.         pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1666.     } else {
  1667. #ifdef LORES_HACK
  1668.     if (currprefs.gfx_lores == 2)
  1669.         pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1670.     else
  1671. #endif
  1672.         pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1673.     }
  1674.  
  1675.     /* The assembly functions work on aligned data, so we may have to do some
  1676.      * additional work at the edges. */
  1677.     if (lframe_end != lframe_end_1) {
  1678.     int i, c = colors_for_drawing.acolors[0];
  1679.     for (i = lframe_end_1; i < lframe_end; i++)
  1680.         xlinebuffer[i] = c;
  1681.     }
  1682.     if (diw_end != diw_end_1) {
  1683.     int i, c = colors_for_drawing.acolors[0];
  1684.     for (i = diw_end; i < diw_end_1; i++)
  1685.         xlinebuffer[i] = c;
  1686.     }
  1687. }
  1688.  
  1689. #undef pfield_linetoscr_full16
  1690. extern void pfield_linetoscr_normal_asm16(void) __asm__("pfield_linetoscr_normal_asm16");
  1691. extern void pfield_linetoscr_ehb_asm16(void) __asm__("pfield_linetoscr_ehb_asm16");
  1692. extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16");
  1693. extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16");
  1694. extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16");
  1695. extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
  1696. extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
  1697. extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
  1698.  
  1699. static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos)
  1700. {
  1701.     int lframe_end_1, diw_end_1;
  1702.  
  1703.     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
  1704.     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
  1705.  
  1706.     if (bplham && bplplanecnt == 6) {
  1707.     pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1708.     } else if (bpldualpf) {
  1709. #ifdef LORES_HACK
  1710.     if (currprefs.gfx_lores == 2)
  1711.         pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
  1712.                    bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1713.     else
  1714. #endif
  1715.         pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
  1716.                    bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1717.     } else if (bplehb) {
  1718. #ifdef LORES_HACK
  1719.     if (currprefs.gfx_lores == 2)
  1720.         pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1721.     else
  1722. #endif
  1723.         pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1724.     } else {
  1725. #ifdef LORES_HACK
  1726.     if (currprefs.gfx_lores == 2)
  1727.         pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1728.     else
  1729. #endif
  1730.         pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1731.     }
  1732.  
  1733.     /* The assembly functions work on aligned data, so we may have to do some
  1734.      * additional work at the edges. */
  1735.     if (lframe_end != lframe_end_1) {
  1736.     int i, c = colors_for_drawing.acolors[0];
  1737.     for (i = lframe_end_1; i < lframe_end; i++)
  1738.         ((uae_u16 *)xlinebuffer)[i] = c;
  1739.     }
  1740.     if (diw_end != diw_end_1) {
  1741.     int i, c = colors_for_drawing.acolors[0];
  1742.     for (i = diw_end; i < diw_end_1; i++)
  1743.         ((uae_u16 *)xlinebuffer)[i] = c;
  1744.     }
  1745. }
  1746.  
  1747. #ifndef NO_DOUBLING_LINETOSCR
  1748. #define NO_DOUBLING_LINETOSCR
  1749. #endif
  1750.  
  1751. #endif
  1752.  
  1753. #ifdef NO_DOUBLING_LINETOSCR
  1754. #undef pfield_linetoscr_full8_double
  1755. #undef pfield_linetoscr_full16_double
  1756. static void pfield_linetoscr_full8_double(int start, int lframe_end, int diw_end, int stop)
  1757. {
  1758.     char *oldxlb = (char *)xlinebuffer;
  1759.     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
  1760.     xlinebuffer = oldxlb + linetoscr_double_offset;
  1761.     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
  1762. }
  1763. static void pfield_linetoscr_full16_double(int start, int lframe_end, int diw_end, int stop)
  1764. {
  1765.     char *oldxlb = (char *)xlinebuffer;
  1766.     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
  1767.     xlinebuffer = oldxlb + linetoscr_double_offset;
  1768.     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
  1769. }
  1770. #endif
  1771.  
  1772. static int linetoscr_diw_end, linetoscr_diw_start;
  1773.  
  1774. /* Initialize the variables necessary for drawing a line.
  1775.  * This involves setting up start/stop positions and display window
  1776.  * borders. Also, since the drawing code may not fully overwrite all
  1777.  * releveant areas in the pixdata.apixels array for speed reasons, parts of
  1778.  * it must possibly be cleared here. */
  1779. static void pfield_init_linetoscr (void)
  1780. {
  1781.     int ddf_left, ddf_right;
  1782.     int mindelay = bpldelay1, maxdelay = bpldelay2;
  1783.     if (bpldelay1 > bpldelay2)
  1784.     maxdelay = bpldelay1, mindelay = bpldelay2;
  1785.  
  1786.     linetoscr_diw_start = dp_for_drawing->diwfirstword;
  1787.     linetoscr_diw_end = dp_for_drawing->diwlastword;
  1788.  
  1789.     /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
  1790.      * so that centering works better, but I'm afraid that might cost too many
  1791.      * cycles. Plus it's dangerous, see the code below that handles the case
  1792.      * with sprites. */
  1793.     if (dip_for_drawing->nr_sprites == 0) {
  1794.     int hiresadjust = bplhires ? 4 : 8;
  1795.     ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1796.     ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1797.  
  1798.     if (linetoscr_diw_start < ddf_left)
  1799.         linetoscr_diw_start = ddf_left;
  1800.     if (linetoscr_diw_end > ddf_right)
  1801.         linetoscr_diw_end = ddf_right;
  1802.  
  1803.     if (mindelay != maxdelay) {
  1804.         /* Raahh...
  1805.          * We just clear the maximum amount of space that may need to be
  1806.          * cleared. We could do this exactly, but it would come out slower
  1807.          * because of the overhead. */
  1808.         int strt = ddf_left;
  1809.         if (currprefs.gfx_lores == 2) {
  1810.         fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
  1811.         fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
  1812.         } else if (currprefs.gfx_lores) {
  1813.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
  1814.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
  1815.         } else {
  1816.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
  1817.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
  1818.         }
  1819.     }
  1820.     } else {
  1821.     int hiresadjust = bplhires ? 4 : 8;
  1822.     /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
  1823.      * Since we have to do a memset anyway (because there may be sprites),
  1824.      * we might as well clear all at once. */
  1825.     ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1826.     ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1827.     if (linetoscr_diw_start < ddf_left) {
  1828.         int strt = linetoscr_diw_start;
  1829.         int stop = ddf_left;
  1830. #ifdef LORES_HACK
  1831.         if (currprefs.gfx_lores == 2)
  1832.         strt >>= 1, stop >>= 1;
  1833. #endif
  1834.         if (strt < stop)
  1835.         fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
  1836.     }
  1837.  
  1838.     if (linetoscr_diw_end > ddf_right) {
  1839.         int strt = ddf_right;
  1840.         int stop = linetoscr_diw_end;
  1841. #ifdef LORES_HACK
  1842.         if (currprefs.gfx_lores == 2)
  1843.         strt >>= 1, stop >>= 1;
  1844. #endif
  1845.         if (strt < stop)
  1846.         fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
  1847.     }
  1848.     }
  1849.     /* Perverse cases happen. */
  1850.     if (linetoscr_diw_end < linetoscr_diw_start)
  1851.     linetoscr_diw_end = linetoscr_diw_start;
  1852. }
  1853.  
  1854. static void pfield_do_linetoscr(int start, int stop)
  1855. {
  1856.     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
  1857.  
  1858.     if (stop > linetoscr_right_x)
  1859.     stop = linetoscr_right_x;
  1860.     if (start < linetoscr_x_adjust)
  1861.     start = linetoscr_x_adjust;
  1862.  
  1863.     if (lframe_end < start)
  1864.     lframe_end = start;
  1865.     if (diw_end > stop)
  1866.     diw_end = stop;
  1867.  
  1868.     if (start >= stop)
  1869.     return;
  1870.  
  1871. #if AGA_CHIPSET == 0
  1872.     if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
  1873.     switch (gfxvidinfo.pixbytes) {
  1874.      case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
  1875.      case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
  1876.      case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
  1877.      case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
  1878.     }
  1879.     } else {
  1880.     switch (gfxvidinfo.pixbytes) {
  1881.      case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
  1882.      case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
  1883.      case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
  1884.      case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
  1885.     }
  1886.     }
  1887. #else
  1888.     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
  1889. #endif
  1890. }
  1891.  
  1892. static void pfield_do_fill_line(int start, int stop)
  1893. {
  1894.     if (stop > linetoscr_right_x)
  1895.     stop = linetoscr_right_x;
  1896.     if (start < linetoscr_x_adjust)
  1897.     start = linetoscr_x_adjust;
  1898.  
  1899.     if (start >= stop)
  1900.     return;
  1901.  
  1902.     switch (gfxvidinfo.pixbytes) {
  1903.      case 1: fill_line_8 (xlinebuffer, start, stop); break;
  1904.      case 2: fill_line_16 (xlinebuffer, start, stop); break;
  1905.      case 3: fill_line_24 (xlinebuffer, start, stop); break;
  1906.      case 4: fill_line_32 (xlinebuffer, start, stop); break;
  1907.     }
  1908. }
  1909.  
  1910. static void pfield_do_linetoscr_full(int double_line)
  1911. {
  1912.     int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
  1913.     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
  1914.     if (lframe_end < start)
  1915.     lframe_end = start;
  1916.     if (diw_end > stop)
  1917.     diw_end = stop;
  1918.  
  1919. #if AGA_CHIPSET == 0
  1920.     if (double_line) {
  1921.     switch (gfxvidinfo.pixbytes) {
  1922.      case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
  1923.      case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
  1924.      case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
  1925.      case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
  1926.     }
  1927.     } else
  1928.     switch (gfxvidinfo.pixbytes) {
  1929.      case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
  1930.      case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
  1931.      case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
  1932.      case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
  1933.     }
  1934. #else
  1935.     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
  1936. #endif
  1937. }
  1938.  
  1939. /* Mouse stuff */
  1940. static void setdontcare(void)
  1941. {
  1942.     write_log ("Don't care mouse mode set\n");
  1943.     mousestate = dont_care_mouse;
  1944.     lastspr0x = lastmx; lastspr0y = lastmy;
  1945.     mstepx = defstepx; mstepy = defstepy;
  1946. }
  1947.  
  1948. static void setfollow(void)
  1949. {
  1950.     write_log ("Follow sprite mode set\n");
  1951.     mousestate = follow_mouse;
  1952.     lastdiffx = lastdiffy = 0;
  1953.     sprvbfl = 0;
  1954.     spr0ctl=spr0pos = 0;
  1955.     mstepx = defstepx; mstepy = defstepy;
  1956. }
  1957.  
  1958. uae_u32 mousehack_helper (void)
  1959. {
  1960.     int mousexpos, mouseypos;
  1961.  
  1962. #ifdef PICASSO96
  1963.     if (picasso_on) {
  1964.     mousexpos = lastmx + picasso96_state.XOffset;
  1965.     mouseypos = lastmy + picasso96_state.YOffset;
  1966.     } else
  1967. #endif
  1968.     {
  1969.     mousexpos = lastmx + linetoscr_x_adjust;
  1970.     if (lastmy >= gfxvidinfo.height)
  1971.         lastmy = gfxvidinfo.height-1;
  1972.     mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
  1973.     mouseypos <<= 1;
  1974.     mousexpos <<= (1-lores_shift);
  1975.     mousexpos += 2*DISPLAY_LEFT_SHIFT;
  1976.     }
  1977.  
  1978.     switch (m68k_dreg (regs, 0)) {
  1979.      case 0:
  1980.     return ievent_alive ? -1 : needmousehack ();
  1981.      case 1:
  1982.     ievent_alive = 10;
  1983.     return mousexpos;
  1984.      case 2:
  1985.     return mouseypos;
  1986.     }
  1987.     return 0;
  1988. }
  1989.  
  1990. void togglemouse(void)
  1991. {
  1992.     switch(mousestate) {
  1993.      case dont_care_mouse: setfollow(); break;
  1994.      case follow_mouse: setdontcare(); break;
  1995.      default: break; /* Nnnnnghh! */
  1996.     }
  1997. }
  1998.  
  1999. static __inline__ int adjust(int val)
  2000. {
  2001.     if (val>127)
  2002.     return 127;
  2003.     else if (val<-127)
  2004.     return -127;
  2005.     return val;
  2006. }
  2007.  
  2008. static void do_mouse_hack(void)
  2009. {
  2010.     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
  2011.     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
  2012.     int diffx, diffy;
  2013.  
  2014.     if (ievent_alive > 0) {
  2015.     mouse_x = mouse_y = 0;
  2016.     return;
  2017.     }
  2018.     switch (mousestate) {
  2019.      case normal_mouse:
  2020.     diffx = lastmx - lastsampledmx;
  2021.     diffy = lastmy - lastsampledmy;
  2022.     if (!newmousecounters) {
  2023.         if (diffx > 127) diffx = 127;
  2024.         if (diffx < -127) diffx = -127;
  2025.         mouse_x += diffx;
  2026.         if (diffy > 127) diffy = 127;
  2027.         if (diffy < -127) diffy = -127;
  2028.         mouse_y += diffy;
  2029.     }
  2030.     lastsampledmx += diffx; lastsampledmy += diffy;
  2031.     break;
  2032.  
  2033.      case dont_care_mouse:
  2034.     diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
  2035.     diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
  2036.     lastspr0x=lastmx; lastspr0y=lastmy;
  2037.     mouse_x+=diffx; mouse_y+=diffy;
  2038.     break;
  2039.  
  2040.      case follow_mouse:
  2041.     if (sprvbfl && sprvbfl-- >1) {
  2042.         int mousexpos, mouseypos;
  2043.  
  2044.         if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x
  2045.         && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff)
  2046.         {
  2047.         int val = (lastdiffx << 16) / (spr0x - lastspr0x);
  2048.         if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
  2049.         }
  2050.         if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
  2051.         && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff)
  2052.         {
  2053.         int val = (lastdiffy<<16) / (spr0y-lastspr0y);
  2054.         if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
  2055.         }
  2056.         mousexpos = lastmx + linetoscr_x_adjust;
  2057.         if (lastmy >= gfxvidinfo.height)
  2058.         lastmy = gfxvidinfo.height-1;
  2059.         mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
  2060.         mouseypos <<= 1;
  2061.         mousexpos <<= (1-lores_shift);
  2062.         mousexpos += 2*DISPLAY_LEFT_SHIFT;
  2063.         diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16);
  2064.         diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16);
  2065.         lastspr0x=spr0x; lastspr0y=spr0y;
  2066.         lastdiffx=diffx; lastdiffy=diffy;
  2067.         mouse_x+=diffx; mouse_y+=diffy;
  2068.     }
  2069.     break;
  2070.     }
  2071. }
  2072.  
  2073.  /*
  2074.   * register functions
  2075.   */
  2076.  
  2077. uae_u16 DMACONR(void)
  2078. {
  2079.     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
  2080.         | (blt_info.blitzero ? 0x2000 : 0));
  2081. }
  2082. static uae_u16 INTENAR(void) { return intena; }
  2083. uae_u16 INTREQR(void)
  2084. {
  2085.     return intreq | (currprefs.use_serial ? 0x0001 : 0);
  2086. }
  2087. static uae_u16 ADKCONR(void) { return adkcon; }
  2088. static uae_u16 VPOSR(void)
  2089. {
  2090. #if AGA_CHIPSET == 1
  2091.     return (vpos >> 8) | lof | 0x2300;
  2092. #elif defined (ECS_AGNUS)
  2093.     return (vpos >> 8) | lof | 0x2000;
  2094. #else
  2095.     return (vpos >> 8) | lof;
  2096. #endif
  2097. }
  2098. static void  VPOSW(uae_u16 v)
  2099. {
  2100.     if (lof != (v & 0x8000))
  2101.     lof_changed = 1;
  2102.     lof = v & 0x8000;
  2103.     /*
  2104.      * This register is much more fun on a real Amiga. You can program
  2105.      * refresh rates with it ;) But I won't emulate this...
  2106.      */
  2107. }
  2108. static uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); }
  2109.  
  2110. static void  COP1LCH(uae_u16 v) { cop1lc= (cop1lc & 0xffff) | ((uae_u32)v << 16); }
  2111. static void  COP1LCL(uae_u16 v) { cop1lc= (cop1lc & ~0xffff) | v; }
  2112. static void  COP2LCH(uae_u16 v) { cop2lc= (cop2lc & 0xffff) | ((uae_u32)v << 16); }
  2113. static void  COP2LCL(uae_u16 v) { cop2lc= (cop2lc & ~0xffff) | v; }
  2114.  
  2115. static void  COPJMP1(uae_u16 a)
  2116. {
  2117.     coplc = cop1lc; copstate = COP_read;
  2118.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  2119.     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
  2120.     copper_active = 1;
  2121.     copper_waiting_for_blitter = 0;
  2122. }
  2123. static void  COPJMP2(uae_u16 a)
  2124. {
  2125.     coplc = cop2lc; copstate = COP_read;
  2126.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  2127.     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
  2128.     copper_active = 1;
  2129.     copper_waiting_for_blitter = 0;
  2130. }
  2131. static void  COPCON(uae_u16 a) { copcon = a; }
  2132. static void  DMACON(uae_u16 v)
  2133. {
  2134.     int i, need_resched = 0;
  2135.  
  2136.     uae_u16 oldcon = dmacon;
  2137.  
  2138.     decide_line();
  2139.     setclr(&dmacon,v); dmacon &= 0x1FFF;
  2140.     /* ??? post_decide_line (); */
  2141.  
  2142.     /* FIXME? Maybe we need to think a bit more about the master DMA enable
  2143.      * bit in these cases. */
  2144.     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
  2145.     COPJMP1(0);
  2146.     }
  2147.     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
  2148.     static int count = 0;
  2149.     if (!count) {
  2150.         count = 1;
  2151.         write_log ("warning: program is doing blitpri hacks.\n");
  2152.     }
  2153.     regs.spcflags |= SPCFLAG_BLTNASTY;
  2154.     }
  2155. #ifndef DONT_WANT_SOUND
  2156.     for (i = 0; i < 4; i++) {
  2157.     struct audio_channel_data *cdp = audio_channel + i;
  2158.  
  2159.     cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i));
  2160.     if (cdp->dmaen) {
  2161.         if (cdp->state == 0) {
  2162.         cdp->state = 1;
  2163.         cdp->pt = cdp->lc;
  2164.         cdp->wper = cdp->per;
  2165.         cdp->wlen = cdp->len;
  2166.         cdp->data_written = 2;
  2167.         eventtab[ev_aud0 + i].oldcycles = eventtab[ev_hsync].oldcycles;
  2168.         eventtab[ev_aud0 + i].evtime = eventtab[ev_hsync].evtime;
  2169.         eventtab[ev_aud0 + i].active = 1;
  2170.         need_resched = 1; /* not _really_ necessary here, but... */
  2171.         }
  2172.     } else {
  2173.         if (cdp->state == 1 || cdp->state == 5) {
  2174.         cdp->state = 0;
  2175.         cdp->current_sample = 0;
  2176.         eventtab[ev_aud0 + i].active = 0;
  2177.         need_resched = 1;
  2178.         }
  2179.     }
  2180.     }
  2181. #endif
  2182.     calculate_copper_cycle_time ();
  2183.     if (copper_active && !eventtab[ev_copper].active) {
  2184.     eventtab[ev_copper].active = 1;
  2185.     eventtab[ev_copper].oldcycles = cycles;
  2186.     eventtab[ev_copper].evtime = 1 + cycles;
  2187.     need_resched = 1;
  2188.     }
  2189.     if (need_resched)
  2190.     events_schedule();
  2191. }
  2192.  
  2193. /*static int trace_intena = 0;*/
  2194.  
  2195. static void  INTENA(uae_u16 v)
  2196. {
  2197. /*    if (trace_intena)
  2198.     fprintf(stderr, "INTENA: %04x\n", v);*/
  2199.     setclr(&intena,v); regs.spcflags |= SPCFLAG_INT;
  2200. }
  2201. void  INTREQ(uae_u16 v)
  2202. {
  2203.     setclr(&intreq,v);
  2204.     regs.spcflags |= SPCFLAG_INT;
  2205.     if ((v&0x8800)==0x0800) serdat&=0xbfff;
  2206. }
  2207.  
  2208. static void  ADKCON(uae_u16 v) { setclr(&adkcon,v); }
  2209.  
  2210. static void  BPLPTH(uae_u16 v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); }
  2211. static void  BPLPTL(uae_u16 v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); }
  2212.  
  2213. static void  BPLCON0(uae_u16 v)
  2214. {
  2215. #if AGA_CHIPSET == 0
  2216.     v &= 0xFF0E;
  2217.     /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect")
  2218.      * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */
  2219.     if ((v & 0xF000) > 0xC000)
  2220.     v &= 0xFFF;
  2221.     /* Don't want 7 lores planes either. */
  2222.     if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000)
  2223.     v &= 0xEFFF;
  2224. #endif
  2225.     if (bplcon0 == v)
  2226.     return;
  2227.     decide_line ();
  2228.     bplcon0 = v;
  2229.     nr_planes_from_bplcon0 = (bplcon0 >> 12) & 7;
  2230.     corrected_nr_planes_from_bplcon0 = ((bplcon0 >> 12) & 7) << (bplcon0 & 0x8000 ? 1 : 0);
  2231.     post_decide_line ();
  2232.     calculate_copper_cycle_time ();
  2233. #if 0
  2234.     calcdiw(); /* This should go away. */
  2235. #endif
  2236. }
  2237. static void  BPLCON1(uae_u16 v)
  2238. {
  2239.     if (bplcon1 == v)
  2240.     return;
  2241.     decide_diw ();
  2242.     bplcon1 = v;
  2243.     decide_delay ();
  2244. }
  2245. static void  BPLCON2(uae_u16 v)
  2246. {
  2247.     if (bplcon2 != v)
  2248.     decide_line ();
  2249.     bplcon2 = v;
  2250. }
  2251. static void  BPLCON3(uae_u16 v)
  2252. {
  2253.     if (bplcon3 != v)
  2254.     decide_line ();
  2255.     bplcon3 = v;
  2256. }
  2257. static void  BPLCON4(uae_u16 v)
  2258. {
  2259.     if (bplcon4 != v)
  2260.     decide_line ();
  2261.     bplcon4 = v;
  2262. }
  2263.  
  2264. static void  BPL1MOD(uae_u16 v)
  2265. {
  2266.     v &= ~1;
  2267.     if ((uae_s16)bpl1mod == (uae_s16)v)
  2268.     return;
  2269.     bpl1mod = v;
  2270.     decide_modulos ();
  2271. }
  2272.  
  2273. static void  BPL2MOD(uae_u16 v)
  2274. {
  2275.     v &= ~1;
  2276.     if ((uae_s16)bpl2mod == (uae_s16)v)
  2277.     return;
  2278.     bpl2mod = v;
  2279.     decide_modulos();
  2280. }
  2281.  
  2282. /* We could do as well without those... */
  2283. static void  BPL1DAT(uae_u16 v) { bpl1dat = v; }
  2284. static void  BPL2DAT(uae_u16 v) { bpl2dat = v; }
  2285. static void  BPL3DAT(uae_u16 v) { bpl3dat = v; }
  2286. static void  BPL4DAT(uae_u16 v) { bpl4dat = v; }
  2287. static void  BPL5DAT(uae_u16 v) { bpl5dat = v; }
  2288. static void  BPL6DAT(uae_u16 v) { bpl6dat = v; }
  2289.  
  2290. static void  DIWSTRT(uae_u16 v)
  2291. {
  2292.     if (diwstrt == v)
  2293.     return;
  2294.     decide_line ();
  2295.     diwstrt = v;
  2296.     calcdiw();
  2297. }
  2298. static void  DIWSTOP(uae_u16 v)
  2299. {
  2300.     if (diwstop == v)
  2301.     return;
  2302.     diwstop = v;
  2303.     calcdiw();
  2304. }
  2305. static void  DDFSTRT(uae_u16 v)
  2306. {
  2307.     v &= 0xFF;
  2308.     if (ddfstrt == v)
  2309.     return;
  2310.     decide_line ();
  2311.     ddfstrt = v;
  2312.     calcdiw();
  2313. }
  2314. static void  DDFSTOP(uae_u16 v)
  2315. {
  2316.     v &= 0xFF;
  2317.     if (ddfstop == v)
  2318.     return;
  2319.     decide_line ();
  2320.     ddfstop = v;
  2321.     calcdiw();
  2322. }
  2323.  
  2324. static void  BLTADAT(uae_u16 v)
  2325. {
  2326.     maybe_blit();
  2327.  
  2328.     blt_info.bltadat = v;
  2329. }
  2330. /*
  2331.  * "Loading data shifts it immediately" says the HRM. Well, that may
  2332.  * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
  2333.  * loaded for every word so that AFWM and ALWM can be applied.
  2334.  */
  2335. static void  BLTBDAT(uae_u16 v)
  2336. {
  2337.     maybe_blit();
  2338.  
  2339.     if (bltcon1 & 2)
  2340.     blt_info.bltbhold = v << (bltcon1 >> 12);
  2341.     else
  2342.     blt_info.bltbhold = v >> (bltcon1 >> 12);
  2343.     blt_info.bltbdat = v;
  2344. }
  2345. static void BLTCDAT(uae_u16 v) { maybe_blit(); blt_info.bltcdat = v; }
  2346.  
  2347. static void BLTAMOD(uae_u16 v) { maybe_blit(); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
  2348. static void BLTBMOD(uae_u16 v) { maybe_blit(); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
  2349. static void BLTCMOD(uae_u16 v) { maybe_blit(); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
  2350. static void BLTDMOD(uae_u16 v) { maybe_blit(); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
  2351.  
  2352. static void BLTCON0(uae_u16 v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; }
  2353. /* The next category is "Most useless hardware register".
  2354.  * And the winner is... */
  2355. static void BLTCON0L(uae_u16 v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); }
  2356. static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; }
  2357.  
  2358. static void BLTAFWM(uae_u16 v) { maybe_blit(); blt_info.bltafwm = v; }
  2359. static void BLTALWM(uae_u16 v) { maybe_blit(); blt_info.bltalwm = v; }
  2360.  
  2361. static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((uae_u32)v << 16); }
  2362. static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); }
  2363. static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((uae_u32)v << 16); }
  2364. static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); }
  2365. static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((uae_u32)v << 16); }
  2366. static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); }
  2367. static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((uae_u32)v << 16); }
  2368. static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); }
  2369. static void BLTSIZE(uae_u16 v)
  2370. {
  2371.     bltsize = v;
  2372.  
  2373.     maybe_blit();
  2374.  
  2375.     blt_info.vblitsize = bltsize >> 6;
  2376.     blt_info.hblitsize = bltsize & 0x3F;
  2377.     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
  2378.     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
  2379.  
  2380.     bltstate = BLT_init;
  2381.     do_blitter();
  2382. }
  2383. static void BLTSIZV(uae_u16 v)
  2384. {
  2385.     maybe_blit();
  2386.     oldvblts = v & 0x7FFF;
  2387. }
  2388. static void BLTSIZH(uae_u16 v)
  2389. {
  2390.     maybe_blit();
  2391.     blt_info.hblitsize = v & 0x7FF;
  2392.     blt_info.vblitsize = oldvblts;
  2393.     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
  2394.     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
  2395.     bltstate = BLT_init;
  2396.     do_blitter();
  2397. }
  2398. static void SPRxCTL_1(uae_u16 v, int num)
  2399. {
  2400.     int sprxp;
  2401.     sprctl[num] = v;
  2402.     nr_armed -= sprarmed[num];
  2403.     sprarmed[num] = 0;
  2404.     if (sprpos[num] == 0 && v == 0) {
  2405.     sprst[num] = SPR_stop;
  2406.     spron[num] = 0;
  2407.     } else
  2408.     sprst[num] = SPR_waiting_start;
  2409.  
  2410.     sprxp = ((sprpos[num] & 0xFF) * 2) + (v & 1) - DISPLAY_LEFT_SHIFT;
  2411.     if (!currprefs.gfx_lores)
  2412.     sprxp *= 2;
  2413.     sprxpos[num] = sprxp;
  2414.     sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
  2415.     sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
  2416. }
  2417. static void SPRxPOS_1(uae_u16 v, int num)
  2418. {
  2419.     int sprxp;
  2420.     sprpos[num] = v;
  2421.     sprxp = ((v & 0xFF) * 2) + (sprctl[num] & 1) - DISPLAY_LEFT_SHIFT;
  2422.     if (!currprefs.gfx_lores)
  2423.     sprxp *= 2;
  2424.     sprxpos[num] = sprxp;
  2425.     sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
  2426. }
  2427. static void SPRxDATA_1(uae_u16 v, int num)
  2428. {
  2429.     sprdata[num] = v;
  2430.     nr_armed += 1 - sprarmed[num];
  2431.     sprarmed[num] = 1;
  2432. }
  2433. static void SPRxDATB_1(uae_u16 v, int num)
  2434. {
  2435.     sprdatb[num] = v;
  2436. }
  2437. static void SPRxDATA(uae_u16 v, int num) { decide_sprites (); SPRxDATA_1 (v, num); }
  2438. static void SPRxDATB(uae_u16 v, int num) { decide_sprites (); SPRxDATB_1 (v, num); }
  2439. static void SPRxCTL(uae_u16 v, int num) { decide_sprites (); SPRxCTL_1 (v, num); }
  2440. static void SPRxPOS(uae_u16 v, int num) { decide_sprites (); SPRxPOS_1 (v, num); }
  2441. static void SPRxPTH(uae_u16 v, int num)
  2442. {
  2443.     decide_line ();
  2444.     sprpt[num] &= 0xffff;
  2445.     sprpt[num] |= (uae_u32)v << 16;
  2446.  
  2447.     if (sprst[num] == SPR_stop || vpos < vblank_endline)
  2448.     sprst[num] = SPR_restart;
  2449.     spron[num] = 1;
  2450. }
  2451. static void SPRxPTL(uae_u16 v, int num)
  2452. {
  2453.     decide_line ();
  2454.     sprpt[num] &= ~0xffff;
  2455.     sprpt[num] |= v;
  2456.  
  2457.     if (sprst[num] == SPR_stop || vpos < vblank_endline)
  2458.     sprst[num] = SPR_restart;
  2459.     spron[num] = 1;
  2460. }
  2461. static void CLXCON(uae_u16 v)
  2462. {
  2463.     clxcon = v;
  2464.     clx_sprmask = (((v >> 15) << 7) | ((v >> 14) << 5) | ((v >> 13) << 3) | ((v >> 12) << 1) | 0x55);
  2465. }
  2466. static uae_u16 CLXDAT(void)
  2467. {
  2468.     uae_u16 v = clxdat;
  2469.     clxdat = 0;
  2470.     return v;
  2471. }
  2472. static void COLOR(uae_u16 v, int num)
  2473. {
  2474.     int r,g,b;
  2475.     int cr,cg,cb;
  2476.     int colreg;
  2477.  
  2478.     v &= 0xFFF;
  2479. #if AGA_CHIPSET == 1
  2480.     {
  2481.     /* XXX Broken */
  2482.     uae_u32 cval;
  2483.     colreg = ((bplcon3 >> 13) & 7) * 32 + num;
  2484.     r = (v & 0xF00) >> 8;
  2485.     g = (v & 0xF0) >> 4;
  2486.     b = (v & 0xF) >> 0;
  2487.     cr = color_regs[colreg] >> 16;
  2488.     cg = (color_regs[colreg] >> 8) & 0xFF;
  2489.     cb = color_regs[colreg] & 0xFF;
  2490.  
  2491.     if (bplcon3 & 0x200) {
  2492.         cr &= 0xF0; cr |= r;
  2493.         cg &= 0xF0; cg |= g;
  2494.         cb &= 0xF0; cb |= b;
  2495.     } else {
  2496.         cr = r + (r << 4);
  2497.         cg = g + (g << 4);
  2498.         cb = b + (b << 4);
  2499.     }
  2500.     cval = (cr << 16) | (cg << 8) | cb;
  2501.     if (cval == color_regs[colreg])
  2502.         return;
  2503.     color_regs[colreg] = cval;
  2504.     pfield_may_need_update(1);
  2505.     }
  2506. #else
  2507.     {
  2508.     if (current_colors.color_regs[num] == v)
  2509.         return;
  2510.     /* Call this with the old table still intact. */
  2511.     record_color_change (num, v);
  2512.     remembered_color_entry = -1;
  2513.     current_colors.color_regs[num] = v;
  2514.     current_colors.acolors[num] = xcolors[v];
  2515.     }
  2516. #endif
  2517. }
  2518.  
  2519. static void  DSKSYNC(uae_u16 v) { dsksync = v; }
  2520. static void  DSKDAT(uae_u16 v) { write_log ("DSKDAT written. Not good.\n"); }
  2521. static void  DSKPTH(uae_u16 v) { dskpt = (dskpt & 0xffff) | ((uae_u32)v << 16); }
  2522. static void  DSKPTL(uae_u16 v) { dskpt = (dskpt & ~0xffff) | (v); }
  2523.  
  2524. static void  DSKLEN(uae_u16 v)
  2525. {
  2526.     if (v & 0x8000) {
  2527.     dskdmaen = dskdmaen == 1 ? 2 : 1;
  2528.     } else {
  2529.     dskdmaen = 0;
  2530.     if (eventtab[ev_diskblk].active)
  2531.         write_log ("warning: Disk DMA aborted!\n");
  2532.     eventtab[ev_diskblk].active = 0;
  2533.     events_schedule();
  2534.  
  2535.     }
  2536.     dsklen = dsklength = v; dsklength &= 0x3fff;
  2537.     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
  2538.     sprintf (warning_buffer, "Non-standard sync: %04x len: %x\n", dsksync, dsklength);
  2539.     write_log (warning_buffer);
  2540.     }
  2541.     if (dskdmaen > 1) {
  2542.     if (dsklen & 0x4000) {
  2543.         eventtab[ev_diskblk].active = 1;
  2544.         eventtab[ev_diskblk].oldcycles = cycles;
  2545.         eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */
  2546.         events_schedule();
  2547.     } else {
  2548.         int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400);
  2549.         if (result) {
  2550.         eventtab[ev_diskblk].active = 1;
  2551.         eventtab[ev_diskblk].oldcycles = cycles;
  2552.         eventtab[ev_diskblk].evtime = result + cycles;
  2553.         events_schedule();
  2554.         }
  2555.     }
  2556.     }
  2557. }
  2558.  
  2559. static uae_u16 DSKBYTR(void)
  2560. {
  2561.     uae_u16 v = (dsklen >> 1) & 0x6000;
  2562.     uae_u16 mfm, byte;
  2563.     if (DISK_GetData(&mfm, &byte))
  2564.     v |= 0x8000;
  2565.     v |= byte;
  2566.     if (dsksync == mfm) v |= 0x1000;
  2567.     return v;
  2568. }
  2569.  
  2570. static uae_u16 DSKDATR(void)
  2571. {
  2572.     uae_u16 mfm, byte;
  2573.     DISK_GetData(&mfm, &byte);
  2574.     return mfm;
  2575. }
  2576.  
  2577. static uae_u16 potgo_value;
  2578.  
  2579. static void POTGO(uae_u16 v)
  2580. {
  2581.     potgo_value = v;
  2582. }
  2583.  
  2584. static uae_u16 POTGOR(void)
  2585. {
  2586.     uae_u16 v = (potgo_value | (potgo_value << 1)) & 0xAA00;
  2587.     v |= v >> 1;
  2588.  
  2589.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2590.     if (buttonstate[2])
  2591.         v &= 0xFBFF;
  2592.  
  2593.     if (buttonstate[1])
  2594.         v &= 0xFEFF;
  2595.     }
  2596.     else if (JSEM_ISJOY0(0, currprefs.fake_joystick) || JSEM_ISJOY1(0, currprefs.fake_joystick)) {
  2597.     if (joy0button & 2) v &= 0xfbff;
  2598.     if (joy0button & 4) v &= 0xfeff;
  2599.     }
  2600.  
  2601.     if (JSEM_ISJOY0(1, currprefs.fake_joystick) || JSEM_ISJOY1(1, currprefs.fake_joystick)) {
  2602.     if (joy1button & 2) v &= 0xbfff;
  2603.     if (joy1button & 4) v &= 0xefff;
  2604.     }
  2605.  
  2606.     return v;
  2607. }
  2608. static uae_u16 POT0DAT(void)
  2609. {
  2610.     static uae_u16 cnt = 0;
  2611.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2612.     if (buttonstate[2])
  2613.         cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
  2614.     if (buttonstate[1])
  2615.         cnt += 0x100;
  2616.     }
  2617.  
  2618.     return cnt;
  2619. }
  2620. static uae_u16 JOY0DAT(void)
  2621. {
  2622.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2623.     do_mouse_hack();
  2624.     return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
  2625.     }
  2626.     return joy0dir;
  2627. }
  2628. static uae_u16 JOY1DAT(void)
  2629. {
  2630.     if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) {
  2631.     do_mouse_hack();
  2632.     return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
  2633.     }
  2634.     return joy1dir;
  2635. }
  2636. static void JOYTEST(uae_u16 v)
  2637. {
  2638.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2639.     mouse_x = v & 0xFC;
  2640.     mouse_y = (v >> 8) & 0xFC;
  2641.     }
  2642. }
  2643. static void AUDxLCH(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16); }
  2644. static void AUDxLCL(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); }
  2645. static void AUDxPER(int nr, uae_u16 v)
  2646. {
  2647.     if (v <= 0) {
  2648. #if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */
  2649.     static int warned = 0;
  2650.     if (!warned)
  2651.         write_log ("Broken program accessing the sound hardware\n"), warned++;
  2652. #endif
  2653.     v = 65535;
  2654.     }
  2655.     if (v < maxhpos/2 && currprefs.produce_sound < 3)
  2656.     v = maxhpos/2;
  2657.  
  2658.     audio_channel[nr].per = v;
  2659. }
  2660.  
  2661. static void AUDxVOL(int nr, uae_u16 v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; }
  2662. static void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; }
  2663.  
  2664. /*
  2665.  * Here starts the copper code. It should be rewritten.
  2666.  */
  2667.  
  2668. #define COPPER_ALTERNATIVE 1
  2669. /*
  2670.  * Calculate the minimum number of cycles after which the
  2671.  * copper comparison becomes true. This is quite tricky. I hope it works.
  2672.  */
  2673. static int calc_copcomp_true(int currvpos, int currhpos)
  2674. {
  2675.     uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2676.     uae_u16 hp = currhpos & (copi2 & 0xFE);
  2677.     uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
  2678.     uae_u16 hcmp = (copi1 & copi2 & 0xFE);
  2679.     int copper_time_hpos;
  2680.     int cycleadd = maxhpos - currhpos;
  2681.     int coptime = 0;
  2682.     int maxwait = 32767;
  2683.  
  2684. #if COPPER_ALTERNATIVE == 0
  2685.     /* This is a kludge... the problem is that there are programs that wait for
  2686.      * FFDDFFFE and then for a line in the second display half, and this doesn't
  2687.      * work without this. I _think_ the reason why it works on the Amiga is that
  2688.      * the last cycle in the line isn't available for the copper, but I'm not sure.
  2689.      * OTOH, I'm pretty convinced that the copper timings are correct otherwise, so
  2690.      * I added this rather than changing something else. */
  2691.     if (hcmp == 0xDC)
  2692.     hcmp += 2;
  2693. #endif
  2694.     decide_line();
  2695.     /* Copper DMA is turned off in Hires 4 bitplane mode */
  2696.     if (vp == vcmp
  2697.     && decided_nr_planes == 4 /* -1 if before plfstrt */
  2698.     && decided_hires
  2699.     && currhpos >= thisline_decision.plfstrt
  2700.     && currhpos < thisline_decision.plfstrt + thisline_decision.plflinelen)
  2701.     coptime += thisline_decision.plfstrt + thisline_decision.plflinelen - currhpos;
  2702.  
  2703.     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
  2704.     return coptime;
  2705.  
  2706.     try_again:
  2707.  
  2708.     while (vp < vcmp) {
  2709.     currvpos++;
  2710.     if (currvpos > maxvpos + 1)
  2711.         return -1;
  2712.     currhpos = 0;
  2713.     coptime += cycleadd;
  2714.     cycleadd = maxhpos;
  2715.     vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2716.     }
  2717.     if ((bplcon0 & 0xF000) == 0xC000) {
  2718.     if (coptime > 0)
  2719.         return coptime;
  2720.     maxwait = plfstrt - current_hpos();
  2721.     if (maxwait < 0)
  2722.         maxwait = 32767;
  2723.     }
  2724.     copper_time_hpos = currhpos;
  2725.     hp = copper_time_hpos & (copi2 & 0xFE);
  2726.     if (!(vp > vcmp)) {
  2727.     while ((int)hp < ((int)hcmp)) {
  2728.         currhpos++;
  2729.         /* Copper DMA is turned off in Hires 4 bitplane mode */
  2730.         if (decided_nr_planes != 4 /* -1 if before plfstrt */
  2731.         || !decided_hires
  2732.         || current_hpos () >= (thisline_decision.plfstrt + thisline_decision.plflinelen))
  2733.         copper_time_hpos++;
  2734.  
  2735.         if (currhpos > maxhpos) {
  2736.         /* Now, what? There might be a good position on the
  2737.          * next line. But it can also be the FFFF FFFE
  2738.          * case.
  2739.          */
  2740.         currhpos = 0;
  2741.         currvpos++;
  2742.         vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2743.         goto try_again;
  2744.         }
  2745.         coptime++;
  2746.         if (coptime >= maxwait)
  2747.         return coptime;
  2748.         hp = copper_time_hpos & (copi2 & 0xFE);
  2749.     }
  2750.     }
  2751.     if (coptime == 0) /* waiting for the blitter */
  2752.     return 1;
  2753.  
  2754.     return coptime;
  2755. }
  2756.  
  2757. /*
  2758.  * Simple version of the above which only tries to get vpos correct.
  2759.  */
  2760. static int calc_copcomp_true_vpos(int currvpos, int currhpos)
  2761. {
  2762.     uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2763.     uae_u16 hp = currhpos & (copi2 & 0xFE);
  2764.     uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
  2765.     uae_u16 hcmp = (copi1 & copi2 & 0xFE);
  2766.     int copper_time_hpos;
  2767.     int cycleadd = maxhpos - currhpos;
  2768.     int coptime = 0;
  2769. #if COPPER_ALTERNATIVE == 0
  2770.     /* see above */
  2771.     if (hcmp == 0xDC)
  2772.     hcmp += 2;
  2773. #endif
  2774.     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
  2775.     return 0;
  2776.  
  2777.     while (vp < vcmp) {
  2778.     currvpos++;
  2779.     if (currvpos > maxvpos + 1)
  2780.         return -1;
  2781.     currhpos = 0;
  2782.     coptime += cycleadd;
  2783.     cycleadd = maxhpos;
  2784.     vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2785.     }
  2786.     return coptime;
  2787. }
  2788.  
  2789. static enum copper_states cop_cmds[4] = { COP_move, COP_wait, COP_move, COP_skip };
  2790.  
  2791. /* This function is not always correct, but it's the best we can do. */
  2792. static int copper_memory_cycles (int n)
  2793. {
  2794.     int current_cycle = current_hpos ();
  2795.     int n_needed = 0;
  2796.     int planes = corrected_nr_planes_from_bplcon0;
  2797.  
  2798.     while (n) {
  2799.     /* This sucks. The DIW may end vertically at exactly this point. Therefore,
  2800.      * we must call decide_line(). If we're vertically outside the DIW,
  2801.      * copper_cycle_time will be != -1 after this call [Sanity Interference] */
  2802.     decide_line ();
  2803. #if COPPER_ALTERNATIVE == 1
  2804.     if (current_cycle >= (maxhpos-3)) {
  2805.         n_needed += maxhpos - current_cycle;
  2806.         current_cycle = 0;
  2807.         continue;
  2808.     }
  2809. #endif
  2810.     if (copper_cycle_time == -1 && current_cycle >= 0x14
  2811.         && current_cycle >= plfstrt && current_cycle < plfstrt + plflinelen
  2812.         && (planes == 6 || (planes == 5 && (current_cycle % 8) < 4)))
  2813.     {
  2814.         n_needed += 4;
  2815.         current_cycle += 4;
  2816.     } else {
  2817.         n_needed += 2;
  2818.         current_cycle += 2;
  2819.     }
  2820.     if (current_cycle >= maxhpos)
  2821.         current_cycle -= maxhpos;
  2822.     n--;
  2823.     }
  2824.     return n_needed;
  2825. }
  2826.  
  2827. static __inline__ int calc_copper_cycles (int n_cycles)
  2828. {
  2829.     return /*copper_cycle_time != -1 ? copper_cycle_time * n_cycles : */copper_memory_cycles (n_cycles);
  2830. }
  2831.  
  2832. static __inline__ int copper_init_read (int n_cycles)
  2833. {
  2834.     if (dmaen(DMA_COPPER)){
  2835.     int t = calc_copper_cycles (n_cycles);
  2836.  
  2837.     eventtab[ev_copper].evtime = t + cycles;
  2838.     return 1;
  2839.     } else {
  2840.     copstate = COP_read;
  2841.     eventtab[ev_copper].active = 0;
  2842.     return 0;
  2843.     }
  2844. }
  2845.  
  2846. static __inline__ void copper_read (void)
  2847. {
  2848.     int cmd;
  2849.  
  2850.     copi1 = chipmem_bank.wget(coplc);
  2851.     copi2 = chipmem_bank.wget(coplc+2);
  2852.     coplc += 4;
  2853.     eventtab[ev_copper].oldcycles = cycles;
  2854.  
  2855.     cmd = (copi1 & 1) | ((copi2 & 1) << 1);
  2856.     copstate = cop_cmds[cmd];
  2857.     eventtab[ev_copper].oldcycles = cycles;
  2858. }
  2859.  
  2860. static __inline__ void handle_bltfinish_wait (void)
  2861. {
  2862.     if (bltstate == BLT_done) {
  2863.     copstate = COP_read;
  2864.     /* Don't need to wait. Experimental: No copper wakeup time in this case. */
  2865.     } else {
  2866.     eventtab[ev_copper].active = 0;
  2867.     copstate = COP_morewait;
  2868.     copper_waiting_for_blitter = 1;
  2869.     }
  2870. }
  2871.  
  2872. void blitter_done_notify (void)
  2873. {
  2874.     if (copper_waiting_for_blitter) {
  2875.     copper_waiting_for_blitter = 0;
  2876.     eventtab[ev_copper].active = 1;
  2877.     eventtab[ev_copper].oldcycles = cycles;
  2878.     eventtab[ev_copper].evtime = 1 + cycles;
  2879.     events_schedule ();
  2880.     }
  2881. }
  2882.  
  2883. static void do_copper_cheat(void)
  2884. {
  2885.     int coptime, t;
  2886.     int nmoves = 100; /*??*/
  2887.     int nextcycles = eventtab[ev_hsync].evtime + currprefs.copper_pos;
  2888.  
  2889.     eventtab[ev_copper].evtime = nextcycles;
  2890.     eventtab[ev_copper].oldcycles = cycles;
  2891.     nextcycles -= cycles;
  2892.  
  2893.     if (!dmaen(DMA_COPPER)) {
  2894.     eventtab[ev_copper].active = 0;
  2895.     return;
  2896.     }
  2897.     for (; nmoves; nmoves--)
  2898.     switch(copstate){
  2899.      case COP_read:
  2900.         copper_read ();
  2901.         break;
  2902.  
  2903.      case COP_read_ignore:
  2904.         copper_read ();
  2905.         copstate = COP_read;
  2906.         break;
  2907.  
  2908.      case COP_move:
  2909.         if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
  2910.         custom_bank.wput(copi1,copi2);
  2911.         copstate = COP_read;
  2912.         } else {
  2913.         copstate = COP_stop;
  2914.         eventtab[ev_copper].active = 0;
  2915.         copper_active = 0;
  2916.         return;
  2917.         }
  2918.         break;
  2919.  
  2920.      case COP_skip:
  2921.         copstate = COP_read;
  2922.         if (calc_copcomp_true(vpos, current_hpos()) == 0)
  2923.         copstate = COP_read_ignore;
  2924.         break;
  2925.  
  2926.      case COP_wait:
  2927.         coptime = calc_copcomp_true(vpos, current_hpos());
  2928.         if (coptime < 0) {
  2929.         copstate = COP_stop;
  2930.         eventtab[ev_copper].active = 0;
  2931.         copper_active = 0;
  2932.         return;
  2933.         }
  2934.         if (coptime == 0) {
  2935.         copper_read();
  2936.         if (vpos != 255)
  2937.             break;
  2938.         eventtab[ev_copper].evtime = cycles + 6;
  2939.         return;
  2940.         }
  2941.         if (coptime >= nextcycles)
  2942.         return;
  2943.         if (vpos == 255)
  2944.         eventtab[ev_copper].evtime = cycles + coptime;
  2945.         /*else
  2946.         copstate = COP_read;*/
  2947.         return;
  2948.  
  2949.      case COP_stop:
  2950.         eventtab[ev_copper].active = 0;
  2951.         copper_active = 0;
  2952.         return;
  2953.  
  2954.      case COP_morewait:
  2955.      case COP_do_read:
  2956.      case COP_do_read_ignore:
  2957.         abort();
  2958.     }
  2959. }
  2960.  
  2961. static void do_copper(void)
  2962. {
  2963.     int coptime, t;
  2964.     for (;;)
  2965.     switch(copstate){
  2966.      case COP_read:
  2967.         eventtab[ev_copper].oldcycles = cycles;
  2968.         if (!copper_init_read (2))
  2969.         return;
  2970.         copstate = COP_do_read;
  2971.         return;
  2972.  
  2973.      case COP_do_read:
  2974.         copper_read ();
  2975.         break;
  2976.  
  2977.      case COP_read_ignore:
  2978.         eventtab[ev_copper].oldcycles = cycles;
  2979.         if (!copper_init_read (2))
  2980.         return;
  2981.         copstate = COP_do_read_ignore;
  2982.         return;
  2983.  
  2984.      case COP_do_read_ignore:
  2985.         copper_read ();
  2986.         copstate = COP_read;
  2987.         break;
  2988.  
  2989.      case COP_move:
  2990.         if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
  2991.         custom_bank.wput(copi1,copi2);
  2992.         copstate = COP_read;
  2993.         break;
  2994.         } else {
  2995.         copstate = COP_stop;
  2996.         eventtab[ev_copper].active = 0;
  2997.         copper_active = 0;
  2998.         }
  2999.         return;
  3000.  
  3001.      case COP_skip:
  3002.         copstate = COP_read;
  3003.         if (calc_copcomp_true(vpos, current_hpos()) == 0)
  3004.         copstate = COP_read_ignore;
  3005.         break;
  3006.  
  3007.      case COP_wait:
  3008.         /* Recognize blitter wait statements. This is a speed optimization
  3009.          * only.*/
  3010.         if (copi1 == 1 && copi2 == 0) {
  3011.         handle_bltfinish_wait ();
  3012.         if (!eventtab[ev_copper].active)
  3013.             return;
  3014.         break;
  3015.         }
  3016.         coptime = calc_copcomp_true_vpos(vpos, current_hpos());
  3017.         if (coptime > 0) {
  3018.         copstate = COP_morewait;
  3019.         eventtab[ev_copper].oldcycles = cycles;
  3020.         eventtab[ev_copper].evtime = coptime + cycles;
  3021.         return;
  3022.         }
  3023.         coptime = calc_copcomp_true(vpos, current_hpos());
  3024.         if (coptime < 0) {
  3025.         copstate = COP_stop;
  3026.         eventtab[ev_copper].active = 0;
  3027.         copper_active = 0;
  3028.         return;
  3029.         }
  3030.         if (coptime) {
  3031.         copstate = COP_morewait;
  3032.         eventtab[ev_copper].evtime = coptime + cycles;
  3033.         return;
  3034.         }
  3035.         copstate = COP_read;
  3036.         /* Experimental: no copper wakeup time in this case. The HRM says
  3037.          * nothing about this. */
  3038.         break;
  3039.  
  3040.      case COP_morewait:
  3041.         coptime = calc_copcomp_true(vpos, current_hpos());
  3042.         if (coptime < 0) {
  3043.         copstate = COP_stop;
  3044.         eventtab[ev_copper].active = 0;
  3045.         copper_active = 0;
  3046.         return;
  3047.         }
  3048.         if (coptime) {
  3049.         eventtab[ev_copper].evtime = coptime + cycles;
  3050.         return;
  3051.         }
  3052.         /* Copper wakeup time: 1 memory cycle, plus 2 for the next read */
  3053.         eventtab[ev_copper].oldcycles = cycles;
  3054.         if (!copper_init_read (3))
  3055.         return;
  3056.         copstate = COP_do_read;
  3057.         return;
  3058.  
  3059.      case COP_stop:
  3060.         eventtab[ev_copper].active = 0;
  3061.         copper_active = 0;
  3062.         return;
  3063.     }
  3064. }
  3065.  
  3066. static void diskblk_handler(void)
  3067. {
  3068.     regs.spcflags |= SPCFLAG_DISK;
  3069.     eventtab[ev_diskblk].active = 0;
  3070. }
  3071.  
  3072. void do_disk(void)
  3073. {
  3074.     if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) {
  3075.     static int warned = 0;
  3076.     if (!warned)
  3077.         warned++, write_log ("BUG!\n");
  3078.     return;
  3079.     }
  3080.     if (dmaen(0x10)){
  3081.     if (dsklen & 0x4000) {
  3082.         if (!chipmem_bank.check (dskpt, 2*dsklength)) {
  3083.         write_log ("warning: Bad disk write DMA pointer\n");
  3084.         } else {
  3085.         uae_u8 *mfmp = get_real_address (dskpt);
  3086.         int i;
  3087.         DISK_InitWrite();
  3088.  
  3089.         for (i = 0; i < dsklength; i++) {
  3090.             uae_u16 d = (*mfmp << 8) + *(mfmp+1);
  3091.             mfmwrite[i] = d;
  3092.             mfmp += 2;
  3093.         }
  3094.         DISK_WriteData(dsklength);
  3095.         }
  3096.     } else {
  3097.         int result = DISK_ReadMFM (dskpt);
  3098.     }
  3099.     regs.spcflags &= ~SPCFLAG_DISK;
  3100.     INTREQ(0x9002);
  3101.     dskdmaen = -1;
  3102.     }
  3103. }
  3104.  
  3105. static void gen_pfield_tables(void)
  3106. {
  3107.     int i;
  3108.     union {
  3109.     struct {
  3110.         uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
  3111.     } foo;
  3112.     struct {
  3113.         uae_u32 a, b, c, d;
  3114.     } bar;
  3115.     } baz;
  3116.  
  3117.     for (i = 0; i < 256; i++) {
  3118.     /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
  3119.     baz.foo.a = i & 64 ? 1 : 0;
  3120.     baz.foo.b = i & 16 ? 1 : 0;
  3121.     baz.foo.c = i & 4 ? 1 : 0;
  3122.     baz.foo.d = i & 1 ? 1 : 0;
  3123.     hirestab_l[i][0] = baz.bar.a;
  3124.  
  3125.     baz.foo.a = i & 128 ? 1 : 0;
  3126.     baz.foo.b = i & 64 ? 1 : 0;
  3127.     baz.foo.c = i & 32 ? 1 : 0;
  3128.     baz.foo.d = i & 16 ? 1 : 0;
  3129.     baz.foo.e = i & 8 ? 1 : 0;
  3130.     baz.foo.f = i & 4 ? 1 : 0;
  3131.     baz.foo.g = i & 2 ? 1 : 0;
  3132.     baz.foo.h = i & 1 ? 1 : 0;
  3133.     lorestab_l[i][0] = baz.bar.a;
  3134.     lorestab_l[i][1] = baz.bar.b;
  3135.     sprtaba[i] = ((((i >> 7) & 1) << 0)
  3136.               | (((i >> 6) & 1) << 2)
  3137.               | (((i >> 5) & 1) << 4)
  3138.               | (((i >> 4) & 1) << 6)
  3139.               | (((i >> 3) & 1) << 8)
  3140.               | (((i >> 2) & 1) << 10)
  3141.               | (((i >> 1) & 1) << 12)
  3142.               | (((i >> 0) & 1) << 14));
  3143.     sprtabb[i] = sprtaba[i] * 2;
  3144.     clxtab[i] = ((((i & 3) && (i & 12)) << 9)
  3145.              | (((i & 3) && (i & 48)) << 10)
  3146.              | (((i & 3) && (i & 192)) << 11)
  3147.              | (((i & 12) && (i & 48)) << 12)
  3148.              | (((i & 12) && (i & 192)) << 13)
  3149.              | (((i & 48) && (i & 192)) << 14));
  3150.     }
  3151.  
  3152.     for (i = 0; i < 256; i++) {
  3153.     baz.foo.a = i & 128 ? 1 : 0;
  3154.     baz.foo.b = i & 64 ? 1 : 0;
  3155.     baz.foo.c = i & 32 ? 1 : 0;
  3156.     baz.foo.d = i & 16 ? 1 : 0;
  3157.     baz.foo.e = i & 8 ? 1 : 0;
  3158.     baz.foo.f = i & 4 ? 1 : 0;
  3159.     baz.foo.g = i & 2 ? 1 : 0;
  3160.     baz.foo.h = i & 1 ? 1 : 0;
  3161.     hirestab_h[i][0] = baz.bar.a;
  3162.     hirestab_h[i][1] = baz.bar.b;
  3163.  
  3164.     baz.foo.a = i & 128 ? 1 : 0;
  3165.     baz.foo.b = i & 128 ? 1 : 0;
  3166.     baz.foo.c = i & 64 ? 1 : 0;
  3167.     baz.foo.d = i & 64 ? 1 : 0;
  3168.     baz.foo.e = i & 32 ? 1 : 0;
  3169.     baz.foo.f = i & 32 ? 1 : 0;
  3170.     baz.foo.g = i & 16 ? 1 : 0;
  3171.     baz.foo.h = i & 16 ? 1 : 0;
  3172.     baz.foo.i = i & 8 ? 1 : 0;
  3173.     baz.foo.j = i & 8 ? 1 : 0;
  3174.     baz.foo.k = i & 4 ? 1 : 0;
  3175.     baz.foo.l = i & 4 ? 1 : 0;
  3176.     baz.foo.m = i & 2 ? 1 : 0;
  3177.     baz.foo.n = i & 2 ? 1 : 0;
  3178.     baz.foo.o = i & 1 ? 1 : 0;
  3179.     baz.foo.p = i & 1 ? 1 : 0;
  3180.     lorestab_h[i][0] = baz.bar.a;
  3181.     lorestab_h[i][1] = baz.bar.b;
  3182.     lorestab_h[i][2] = baz.bar.c;
  3183.     lorestab_h[i][3] = baz.bar.d;
  3184.     }
  3185. }
  3186.  
  3187. static void do_sprites(int currvp, int currhp)
  3188. {
  3189.     int i;
  3190.     /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is
  3191.      * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */
  3192.     int maxspr = currhp/4 - 0x14/4;
  3193. #if 0
  3194.     if (currvp == 0)
  3195.     return;
  3196. #else
  3197.     /* I don't know whether this is right. Some programs write the sprite pointers
  3198.      * directly at the start of the copper list. With the currvp==0 check, the
  3199.      * first two words of data are read on the second line in the frame. The problem
  3200.      * occurs when the program jumps to another copperlist a few lines further down
  3201.      * which _also_ writes the sprite pointer registers. This means that a) writing
  3202.      * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
  3203.      * is disabled until the end of the vertical blanking interval. The HRM
  3204.      * isn't clear - it says that the vertical sprite position can be set to any
  3205.      * value, but this wouldn't be the first mistake... */
  3206.     /* Update: I modified one of the programs to write the sprite pointers the
  3207.      * second time only _after_ the VBlank interval, and it showed the same behaviour
  3208.      * as it did unmodified under UAE with the above check. This indicates that the
  3209.      * solution below is correct. */
  3210.     if (currvp < vblank_endline)
  3211.     return;
  3212. #endif
  3213.     if (maxspr < 0)
  3214.     return;
  3215.     if (maxspr > 8)
  3216.     maxspr = 8;
  3217.  
  3218.     for (i = 0; i < maxspr; i++) {
  3219.     int fetch = 0;
  3220.  
  3221.     if (spron[i] == 0)
  3222.         continue;
  3223.  
  3224.     if (sprst[i] == SPR_restart) {
  3225.         fetch = 2;
  3226.         spron[i] = 1;
  3227.     } else if ((sprst[i] == SPR_waiting_start && sprvstart[i] == vpos) || sprst[i] == SPR_waiting_stop) {
  3228.         fetch = 1;
  3229.         sprst[i] = SPR_waiting_stop;
  3230.     }
  3231.     if (sprst[i] == SPR_waiting_stop && sprvstop[i] == vpos) {
  3232.         fetch = 2;
  3233.         sprst[i] = SPR_waiting_start;
  3234.     }
  3235.  
  3236.     if (fetch && dmaen(DMA_SPRITE)) {
  3237.         uae_u16 data1 = chipmem_bank.wget(sprpt[i]);
  3238.         uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2);
  3239.         sprpt[i] += 4;
  3240.  
  3241.         if (fetch == 1) {
  3242.         /* Hack for X mouse auto-calibration */
  3243.         if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
  3244.             spr0ctl=sprctl[0];
  3245.             spr0pos=sprpos[0];
  3246.             sprvbfl=2;
  3247.         }
  3248.         SPRxDATB_1(data2, i);
  3249.         SPRxDATA_1(data1, i);
  3250.         } else {
  3251.         SPRxPOS_1(data1, i);
  3252.         SPRxCTL_1(data2, i);
  3253.         }
  3254.     }
  3255.     }
  3256. }
  3257.  
  3258. static uae_u32 attach_2nd;
  3259.  
  3260. static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
  3261. {
  3262.     int j;
  3263.     int sprxp = spd[i].linepos;
  3264.     uae_u32 datab = spd[i].datab;
  3265.     uae_u32 mask2 = 0;
  3266.     int sbit = 1 << spd[i].num;
  3267.     int sprx_shift = 1;
  3268.     int attach_compare = -1;
  3269.     if (currprefs.gfx_lores != 1)
  3270.     sprx_shift = 0;
  3271.  
  3272.     attach_2nd = 0;
  3273.     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
  3274.     attach_compare = spd[i].num - 1;
  3275.  
  3276.     for (j = prev_overlap; j < i; j++) {
  3277.     uae_u32 mask1;
  3278.     int off;
  3279.  
  3280.     if (spd[i].num < spd[j].num)
  3281.         continue;
  3282.  
  3283.     off = sprxp - spd[j].linepos;
  3284.     off <<= sprx_shift;
  3285.     mask1 = spd[j].datab >> off;
  3286.  
  3287.     /* If j is an attachment for i, then j doesn't block i */
  3288.     if (spd[j].num == attach_compare) {
  3289.         attach_2nd |= mask1;
  3290.     } else {
  3291.         mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
  3292.         mask1 |= (mask1 & 0x55555555) << 1;
  3293.         if (datab & mask1)
  3294.         clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
  3295.         mask2 |= mask1;
  3296.     }
  3297.     }
  3298.     for (j = i+1; j < nr_spr; j++) {
  3299.     uae_u32 mask1;
  3300.     int off = spd[j].linepos - sprxp;
  3301.  
  3302.     if (off >= sprite_width || spd[i].num < spd[j].num)
  3303.         break;
  3304.  
  3305.     off <<= sprx_shift;
  3306.     mask1 = spd[j].datab << off;
  3307.  
  3308.     /* If j is an attachment for i, then j doesn't block i */
  3309.     if (spd[j].num == attach_compare) {
  3310.         attach_2nd |= mask1;
  3311.     } else {
  3312.         mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
  3313.         mask1 |= (mask1 & 0x55555555) << 1;
  3314.         if (datab & mask1)
  3315.         clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
  3316.         mask2 |= mask1;
  3317.     }
  3318.     }
  3319.     datab &= ~mask2;
  3320.     return datab;
  3321. }
  3322.  
  3323. static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
  3324. {
  3325.     uae_u32 datcd;
  3326.     int basecol = 16;
  3327.     if (!attch)
  3328.     basecol += (spr & ~1)*2;
  3329.     if (bpldualpf)
  3330.     basecol |= 128;
  3331.     if (attch)
  3332.     datcd = attach_2nd;
  3333.  
  3334.     for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
  3335.     int col;
  3336.  
  3337.     if (attch) {
  3338.         col = ((datab & 3) << 2) | (datcd & 3);
  3339.         datcd >>= 2;
  3340.     } else
  3341.         col = datab & 3;
  3342.     datab >>= 2;
  3343.     if (col) {
  3344.         col |= basecol;
  3345.         if (ham) {
  3346.         col = colors_for_drawing.color_regs[col];
  3347.         ham_linebuf[sprxp] = col;
  3348.         if (sprx_inc == 2) {
  3349.             ham_linebuf[sprxp+1] = col;
  3350.         }
  3351.         } else {
  3352.         pixdata.apixels[sprxp] = col;
  3353.         if (sprx_inc == 2) {
  3354.             pixdata.apixels[sprxp+1] = col;
  3355.         }
  3356.         }
  3357.     }
  3358.     }
  3359. }
  3360.  
  3361. static void walk_sprites (struct sprite_draw *spd, int nr_spr)
  3362. {
  3363.     int i, prev_overlap;
  3364.     int last_sprite_pos = -64;
  3365.     uae_u32 plane1 = 0, plane2 = 0;
  3366.     int sprx_inc = 1, sprx_shift = 1;
  3367.  
  3368.     if (currprefs.gfx_lores == 0)
  3369.     sprx_inc = 2, sprx_shift = 0;
  3370.  
  3371.     prev_overlap = 0;
  3372.     for (i = 0; i < nr_spr; i++) {
  3373.     int sprxp = spd[i].linepos;
  3374.     int m = 1 << spd[i].num;
  3375.     uae_u32 datab;
  3376.     while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
  3377.         prev_overlap++;
  3378.  
  3379.     datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
  3380. #ifdef LORES_HACK
  3381.     if (currprefs.gfx_lores == 2)
  3382.         sprxp >>= 1;
  3383. #endif
  3384.     if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
  3385.         if (sprxp != last_sprite_pos) {
  3386.         int ok = last_sprite_pos-sprxp+16;
  3387.         int ok2;
  3388.         if (ok <= 0) {
  3389.             ok = ok2 = 0;
  3390.             plane1 = 0;
  3391.             plane2 = 0;
  3392.         } else {
  3393.             ok2 = ok << sprx_shift;
  3394.             plane1 >>= 32 - ok2;
  3395.             plane2 >>= 32 - ok2;
  3396.         }
  3397.         last_sprite_pos = sprxp;
  3398.  
  3399.         if (bpldualpf) {
  3400.             uae_u32 mask = 3 << ok2;
  3401.             int p = sprxp+ok;
  3402.  
  3403.             for (; mask; mask <<= 2, p += sprx_inc) {
  3404.             int data = pixdata.apixels[p];
  3405.             if (dblpf_2nd2[data] == 2)
  3406.                 plane2 |= mask;
  3407.             if (dblpf_2nd1[data] == 1)
  3408.                 plane1 |= mask;
  3409.             }
  3410.         } else {
  3411.             uae_u32 mask = 3 << ok2;
  3412.             int p = sprxp+ok;
  3413.  
  3414.             for (; mask; mask <<= 2, p += sprx_inc) {
  3415.             if (pixdata.apixels[p])
  3416.                 plane2 |= mask;
  3417.             }
  3418.         }
  3419.         }
  3420.         if (bpldualpf && m >= plfpri[1]) {
  3421.         datab &= ~plane1;
  3422.         attach_2nd &= ~plane1;
  3423.         }
  3424.         if (m >= plfpri[2]) {
  3425.         datab &= ~plane2;
  3426.         attach_2nd &= ~plane2;
  3427.         }
  3428.     }
  3429.     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
  3430.         /* Attached sprite */
  3431.         if (bplham) {
  3432.         if (sprx_inc == 1) {
  3433.             render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
  3434.         } else {
  3435.             render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
  3436.         }
  3437.         } else {
  3438.         if (sprx_inc == 1) {
  3439.             render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
  3440.         } else {
  3441.             render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
  3442.         }
  3443.         }
  3444.         /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
  3445.         if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
  3446.         i++;
  3447.     } else {
  3448.         if (bplham) {
  3449.         if (sprx_inc == 1) {
  3450.             render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
  3451.         } else {
  3452.             render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
  3453.         }
  3454.         } else {
  3455.         if (sprx_inc == 1) {
  3456.             render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
  3457.         } else {
  3458.             render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
  3459.         }
  3460.         }
  3461.     }
  3462.     }
  3463. }
  3464.  
  3465. #ifndef SMART_UPDATE
  3466. #undef UNALIGNED_PROFITABLE
  3467. #endif
  3468.  
  3469. #ifdef UNALIGNED_PROFITABLE
  3470.  
  3471. static void pfield_doline_unaligned_h (int lineno)
  3472. {
  3473.     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
  3474.  
  3475.     if (bplhires) {
  3476.     int xpos1 = xpos + 16 + bpldelay1*2;
  3477.     int xpos2;
  3478.     uae_u8 *dataptr = line_data[lineno];
  3479.     int len = dp_for_drawing->plflinelen >> 1;
  3480.  
  3481.     if (len <= 0)
  3482.         return;
  3483.  
  3484.     if (bpldelay1 == bpldelay2) {
  3485.         switch (bplplanecnt) {
  3486.          case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3487.          case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3488.          case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3489.          case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3490.          case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3491.          case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3492.          case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3493.          case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3494.         }
  3495.     } else {
  3496.         switch (bplplanecnt) {
  3497.          case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3498.          case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3499.          case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3500.          case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3501.         }
  3502.  
  3503.         dataptr += MAX_WORDS_PER_LINE*2;
  3504.         xpos2 = xpos + 16 + bpldelay2*2;
  3505.         switch (bplplanecnt) {
  3506.          case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3507.          case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3508.          case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3509.          case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3510.         }
  3511.     }
  3512.     } else {
  3513.     int xpos1 = xpos + 32 + bpldelay1*2;
  3514.     int xpos2;
  3515.     uae_u8 *dataptr = line_data[lineno];
  3516.     int len = dp_for_drawing->plflinelen >> 2;
  3517.  
  3518.     if (len <= 0)
  3519.         return;
  3520.  
  3521.     if (bpldelay1 == bpldelay2) {
  3522.         switch (bplplanecnt) {
  3523.          case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3524.          case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3525.          case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3526.          case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3527.          case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3528.          case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3529.          case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3530.          case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3531.         }
  3532.     } else {
  3533.         switch (bplplanecnt) {
  3534.          case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3535.          case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3536.          case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3537.          case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3538.         }
  3539.  
  3540.         dataptr += MAX_WORDS_PER_LINE*2;
  3541.         xpos2 = xpos + 32 + bpldelay2*2;
  3542.         switch (bplplanecnt) {
  3543.          case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3544.          case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3545.          case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3546.          case 8:         set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3547.         }
  3548.     }
  3549.     }
  3550. }
  3551.  
  3552. static void pfield_doline_unaligned_l (int lineno)
  3553. {
  3554.     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
  3555.  
  3556.     if (bplhires) {
  3557.     int xpos1 = xpos + 8 + bpldelay1;
  3558.     int xpos2;
  3559.     uae_u8 *dataptr = line_data[lineno];
  3560.     int len = dp_for_drawing->plflinelen >> 1;
  3561.  
  3562.     if (len <= 0)
  3563.         return;
  3564.  
  3565.     if (bpldelay1 == bpldelay2) {
  3566.         switch (bplplanecnt) {
  3567.          case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3568.          case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3569.          case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3570.          case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3571.          case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3572.          case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3573.          case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3574.          case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3575.         }
  3576.     } else {
  3577.         switch (bplplanecnt) {
  3578.          case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3579.          case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3580.          case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3581.          case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3582.         }
  3583.  
  3584.         xpos2 = xpos + 8 + bpldelay2;
  3585.         switch (bplplanecnt) {
  3586.          case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3587.          case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3588.          case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3589.          case 8:         set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3590.         }
  3591.     }
  3592.     } else {
  3593.     int xpos1 = xpos + 16 + bpldelay1;
  3594.     int xpos2;
  3595.     uae_u8 *dataptr = line_data[lineno];
  3596.     int len = dp_for_drawing->plflinelen >> 2;
  3597.  
  3598.     if (len <= 0)
  3599.         return;
  3600.  
  3601.     if (bpldelay1 == bpldelay2) {
  3602.         switch (bplplanecnt) {
  3603.          case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3604.          case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3605.          case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3606.          case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3607.          case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3608.          case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3609.          case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3610.          case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3611.         }
  3612.     } else {
  3613.         switch (bplplanecnt) {
  3614.          case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3615.          case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3616.          case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3617.          case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
  3618.         }
  3619.  
  3620.         xpos2 = xpos + 16 + bpldelay2;
  3621.         switch (bplplanecnt) {
  3622.          case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3623.          case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3624.          case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3625.          case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
  3626.         }
  3627.     }
  3628.     }
  3629. }
  3630.  
  3631. #define pfield_doline_h pfield_doline_unaligned_h
  3632. #define pfield_doline_l pfield_doline_unaligned_l
  3633.  
  3634. #else /* not UNALIGNED_PROFITABLE */
  3635.  
  3636.  
  3637. static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
  3638. {
  3639.     uae_u32 *pixptr = (uae_u32 *)dp;
  3640.  
  3641.     *pixptr |= hirestab_h[data >> 8][0] << bit;
  3642.     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
  3643.     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
  3644.     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
  3645. }
  3646.  
  3647. static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
  3648. {
  3649.     uae_u32 *pixptr = (uae_u32 *)dp;
  3650.  
  3651.     *pixptr |= lorestab_h[data >> 8][0] << bit;
  3652.     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
  3653.     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
  3654.     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
  3655.     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
  3656.     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
  3657.     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
  3658.     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
  3659. }
  3660.  
  3661. static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
  3662. {
  3663.     uae_u32 *pixptr = (uae_u32 *)dp;
  3664.  
  3665.     *pixptr = hirestab_h[data >> 8][0] << bit;
  3666.     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
  3667.     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
  3668.     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
  3669. }
  3670.  
  3671. static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
  3672. {
  3673.     uae_u32 *pixptr = (uae_u32 *)dp;
  3674.  
  3675.     *pixptr = lorestab_h[data >> 8][0] << bit;
  3676.     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
  3677.     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
  3678.     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
  3679.     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
  3680.     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
  3681.     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
  3682.     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
  3683. }
  3684.  
  3685. static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
  3686. {
  3687.     uae_u32 *pixptr = (uae_u32 *)dp;
  3688.  
  3689.     *pixptr |= hirestab_l[data >> 8][0] << bit;
  3690.     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
  3691. }
  3692.  
  3693. static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
  3694. {
  3695.     uae_u32 *pixptr = (uae_u32 *)dp;
  3696.  
  3697.     *pixptr |= lorestab_l[data >> 8][0] << bit;
  3698.     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
  3699.     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
  3700.     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
  3701. }
  3702.  
  3703. static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
  3704. {
  3705.     uae_u32 *pixptr = (uae_u32 *)dp;
  3706.  
  3707.     *pixptr = hirestab_l[data >> 8][0] << bit;
  3708.     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
  3709. }
  3710.  
  3711. static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
  3712. {
  3713.     uae_u32 *pixptr = (uae_u32 *)dp;
  3714.  
  3715.     *pixptr = lorestab_l[data >> 8][0] << bit;
  3716.     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
  3717.     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
  3718.     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
  3719. }
  3720.  
  3721. #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
  3722.     int i; \
  3723.     unsigned int bpldat1; \
  3724.     uae_u16 data; \
  3725.     unsigned int bpldat2 = 0; \
  3726.     uae_u8 *ptr = (POINTER); \
  3727.     for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
  3728.     bpldat1 = bpldat2; \
  3729.     bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
  3730.     ptr+=2; \
  3731.     data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
  3732.     FUNC(data, app, MULT); \
  3733.     app += P_ADD; \
  3734.     } \
  3735.     data = bpldat2 << (16 - DELAY); \
  3736.     FUNC(data, app, MULT); \
  3737. }
  3738.  
  3739. #ifdef SMART_UPDATE
  3740. #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
  3741. #else
  3742. #define DATA_POINTER(n) (real_bplpt[n])
  3743. #endif
  3744.  
  3745. static void pfield_doline_aligned_h (int lineno)
  3746. {
  3747.     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
  3748.  
  3749.     if (bplhires) {
  3750.     if (bplplanecnt > 0) {
  3751.         int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
  3752.         int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
  3753.         int delay1 = 2*(bpldelay1 & 7);
  3754.         int delay2 = 2*(bpldelay2 & 7);
  3755.         unsigned char *app = pixdata.apixels + xpos1;
  3756.         uae_u8 *dataptr = line_data[lineno];
  3757.  
  3758.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
  3759.         if (bplplanecnt > 2) {
  3760.         app = pixdata.apixels + xpos1;
  3761.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
  3762.         }
  3763. #if AGA_CHIPSET == 1
  3764.         if (bplplanecnt > 4) {
  3765.         app = pixdata.apixels + xpos1;
  3766.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
  3767.         }
  3768.         if (bplplanecnt > 6) {
  3769.         app = pixdata.apixels + xpos1;
  3770.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
  3771.         }
  3772. #endif
  3773.         if (bplplanecnt > 1) {
  3774.         app = pixdata.apixels + xpos2;
  3775.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
  3776.         }
  3777.         if (bplplanecnt > 3) {
  3778.         app = pixdata.apixels + xpos2;
  3779.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
  3780.         }
  3781. #if AGA_CHIPSET == 1
  3782.         if (bplplanecnt > 5) {
  3783.         app = pixdata.apixels + xpos2;
  3784.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
  3785.         }
  3786.         if (bplplanecnt > 7) {
  3787.         app = pixdata.apixels + xpos2;
  3788.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
  3789.         }
  3790. #endif
  3791.     } else {
  3792.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  3793.     }
  3794.     } else {
  3795.     if (bplplanecnt > 0) {
  3796.         int x = xpos + 32;
  3797.         unsigned char *app = pixdata.apixels + x;
  3798.         uae_u8 *dataptr = line_data[lineno];
  3799.  
  3800.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
  3801.         if (bplplanecnt > 2) {
  3802.         app = pixdata.apixels + x;
  3803.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
  3804.         }
  3805.         if (bplplanecnt > 4) {
  3806.         app = pixdata.apixels + x;
  3807.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
  3808.         }
  3809. #if AGA_CHIPSET == 1
  3810.         if (bplplanecnt > 6) {
  3811.         app = pixdata.apixels + x;
  3812.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
  3813.         }
  3814. #endif
  3815.         if (bplplanecnt > 1) {
  3816.         app = pixdata.apixels + x;
  3817.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
  3818.         }
  3819.         if (bplplanecnt > 3) {
  3820.         app = pixdata.apixels + x;
  3821.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
  3822.         }
  3823.         if (bplplanecnt > 5) {
  3824.         app = pixdata.apixels + x;
  3825.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
  3826.         }
  3827. #if AGA_CHIPSET == 1
  3828.         if (bplplanecnt > 7) {
  3829.         app = pixdata.apixels + x;
  3830.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
  3831.         }
  3832. #endif
  3833.     } else {
  3834.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  3835.     }
  3836.     }
  3837. }
  3838.  
  3839. static void pfield_doline_aligned_l (int lineno)
  3840. {
  3841.     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
  3842.  
  3843.     if (bplhires) {
  3844.     if (bplplanecnt > 0) {
  3845.         int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
  3846.         int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
  3847.         int delay1 = (bpldelay1 & 7) * 2;
  3848.         int delay2 = (bpldelay2 & 7) * 2;
  3849.         unsigned char *app = pixdata.apixels + xpos1;
  3850.         uae_u8 *dataptr = line_data[lineno];
  3851.  
  3852.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
  3853.         if (bplplanecnt > 2) {
  3854.         app = pixdata.apixels + xpos1;
  3855.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
  3856.         }
  3857. #if AGA_CHIPSET == 1
  3858.         if (bplplanecnt > 4) {
  3859.         app = pixdata.apixels + xpos1;
  3860.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
  3861.         }
  3862.         if (bplplanecnt > 6) {
  3863.         app = pixdata.apixels + xpos1;
  3864.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
  3865.         }
  3866. #endif
  3867.         if (bplplanecnt > 1) {
  3868.         app = pixdata.apixels + xpos2;
  3869.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
  3870.         }
  3871.         if (bplplanecnt > 3) {
  3872.         app = pixdata.apixels + xpos2;
  3873.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
  3874.         }
  3875. #if AGA_CHIPSET == 1
  3876.         if (bplplanecnt > 5) {
  3877.         app = pixdata.apixels + xpos2;
  3878.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
  3879.         }
  3880.         if (bplplanecnt > 7) {
  3881.         app = pixdata.apixels + xpos2;
  3882.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
  3883.         }
  3884. #endif
  3885.     } else {
  3886.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  3887.     }
  3888.     } else {
  3889.     if (bplplanecnt > 0) {
  3890.         int x = xpos + 16;
  3891.         int delay1 = bpldelay1;
  3892.         int delay2 = bpldelay2;
  3893.         unsigned char *app = pixdata.apixels + x;
  3894.         uae_u8 *dataptr = line_data[lineno];
  3895.  
  3896.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
  3897.         if (bplplanecnt > 2) {
  3898.         app = pixdata.apixels + x;
  3899.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
  3900.         }
  3901.         if (bplplanecnt > 4) {
  3902.         app = pixdata.apixels + x;
  3903.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
  3904.         }
  3905. #if AGA_CHIPSET == 1
  3906.         if (bplplanecnt > 6) {
  3907.         app = pixdata.apixels + x;
  3908.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
  3909.         }
  3910. #endif
  3911.         if (bplplanecnt > 1) {
  3912.         app = pixdata.apixels + x;
  3913.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
  3914.         }
  3915.         if (bplplanecnt > 3) {
  3916.         app = pixdata.apixels + x;
  3917.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
  3918.         }
  3919.         if (bplplanecnt > 5) {
  3920.         app = pixdata.apixels + x;
  3921.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
  3922.         }
  3923. #if AGA_CHIPSET == 1
  3924.         if (bplplanecnt > 7) {
  3925.         app = pixdata.apixels + x;
  3926.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
  3927.         }
  3928. #endif
  3929.     } else {
  3930.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  3931.     }
  3932.     }
  3933. }
  3934.  
  3935. #define pfield_doline_h pfield_doline_aligned_h
  3936. #define pfield_doline_l pfield_doline_aligned_l
  3937.  
  3938. #endif /* UNALIGNED_PROFITABLE */
  3939.  
  3940. static void pfield_adjust_delay (void)
  3941. {
  3942.     int ddf_left = dp_for_drawing->plfstrt;
  3943.     int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
  3944.     int i;
  3945.  
  3946.     for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
  3947.     int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
  3948.     int delay1 = delayreg & 0xF;
  3949.     int delay2 = (delayreg >> 4) & 0xF;
  3950.     int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
  3951.     int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
  3952.     int j;
  3953.     startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
  3954.     stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
  3955.     if (currprefs.gfx_lores == 0)
  3956.         delay1 <<= 1, delay2 <<= 1;
  3957.     else if (currprefs.gfx_lores == 2)
  3958.         startpos >>= 1, stoppos >>= 1;
  3959.     for (j = startpos-1; j >= stoppos; j--) {
  3960.         pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
  3961.     }
  3962.     }
  3963. }
  3964.  
  3965. static void init_sprites (void)
  3966. {
  3967.     int i;
  3968.  
  3969.     for (i = 0; i < 8; i++) {
  3970.     /* ???? */
  3971.     sprst[i] = SPR_stop;
  3972.     spron[i] = 0;
  3973.     }
  3974.  
  3975.     memset(sprpos, 0, sizeof sprpos);
  3976.     memset(sprctl, 0, sizeof sprctl);
  3977. }
  3978.  
  3979. static void init_hardware_frame (void)
  3980. {
  3981.     next_lineno = 0;
  3982.     nln_how = 0;
  3983.     diwstate = DIW_waiting_start;
  3984.     hdiwstate = DIW_waiting_start;
  3985. }
  3986.  
  3987. void init_row_map(void)
  3988. {
  3989.     int i;
  3990.     if (gfxvidinfo.height > 2048) {
  3991.     write_log ("Resolution too high, aborting\n");
  3992.     }
  3993.     for (i = 0; i < gfxvidinfo.height + 1; i++)
  3994.     row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
  3995. }
  3996.  
  3997. /* @@@ Are those still useful? */
  3998.  
  3999. /*
  4000.  * A raster line has been built in the graphics buffer. Tell the graphics code
  4001.  * to do anything necessary to display it.
  4002.  */
  4003. static __inline__ void do_flush_line_1 (int lineno)
  4004. {
  4005.     if (lineno < first_drawn_line)
  4006.     first_drawn_line = lineno;
  4007.     if (lineno > last_drawn_line)
  4008.     last_drawn_line = lineno;
  4009.  
  4010.     if (gfxvidinfo.maxblocklines == 0)
  4011.     flush_line(lineno);
  4012.     else {
  4013.     if ((last_block_line+1) != lineno) {
  4014.         if (first_block_line != -2)
  4015.         flush_block (first_block_line, last_block_line);
  4016.         first_block_line = lineno;
  4017.     }
  4018.     last_block_line = lineno;
  4019.     if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
  4020.         flush_block (first_block_line, last_block_line);
  4021.         first_block_line = last_block_line = -2;
  4022.     }
  4023.     }
  4024. }
  4025.  
  4026. static void do_flush_line (int lineno)
  4027. {
  4028.     /* We don't want to call X libraries from the second thread right now. */
  4029. #ifndef SUPPORT_PENGUINS
  4030.     do_flush_line_1 (lineno);
  4031. #else
  4032.     line_drawn[lineno] = 1;
  4033. #endif
  4034. }
  4035.  
  4036. /*
  4037.  * One drawing frame has been finished. Tell the graphics code about it.
  4038.  * Note that the actual flush_screen() call is a no-op for all reasonable
  4039.  * systems.
  4040.  */
  4041.  
  4042. static void do_flush_screen (int start, int stop)
  4043. {
  4044.     int i;
  4045. #ifdef SUPPORT_PENGUINS
  4046.     for (i = 0; i < gfxvidinfo.height; i++) {
  4047.     if (line_drawn[i])
  4048.         do_flush_line_1 (i);
  4049.     }
  4050. #endif
  4051.     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
  4052.     flush_block (first_block_line, last_block_line);
  4053.     }
  4054.     if (start <= stop)
  4055.     flush_screen (start, stop);
  4056. }
  4057.  
  4058. static void adjust_drawing_colors (int ctable, int bplham)
  4059. {
  4060.     if (drawing_color_matches != ctable) {
  4061.     if (bplham) {
  4062.         memcpy (&colors_for_drawing, curr_color_tables + ctable,
  4063.             sizeof colors_for_drawing);
  4064.         color_match_type = color_match_full;
  4065.     } else {
  4066.         memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
  4067.             sizeof colors_for_drawing.acolors);
  4068.         color_match_type = color_match_acolors;
  4069.     }
  4070.     drawing_color_matches = ctable;
  4071.     } else if (bplham && color_match_type != color_match_full) {
  4072.     memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
  4073.         sizeof colors_for_drawing.color_regs);
  4074.     color_match_type = color_match_full;
  4075.     }
  4076. }
  4077.  
  4078. static __inline__ void adjust_color0_for_color_change (void)
  4079. {
  4080.     drawing_color_matches = -1;
  4081.     if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
  4082.     colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
  4083.     colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
  4084.     }
  4085. }
  4086.  
  4087. static __inline__ void do_color_changes (line_draw_func worker)
  4088. {
  4089.     int lastpos = 0, nextpos, i;
  4090.     struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
  4091.  
  4092.     for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
  4093.     if (i == dip_for_drawing->last_color_change)
  4094.         nextpos = max_diwlastword;
  4095.     else
  4096.         nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
  4097.     worker (lastpos, nextpos);
  4098.     if (i != dip_for_drawing->last_color_change) {
  4099.         colors_for_drawing.color_regs[cc->regno] = cc->value;
  4100.         colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
  4101.     }
  4102.     if (nextpos > lastpos) {
  4103.         lastpos = nextpos;
  4104.         if (lastpos >= linetoscr_right_x)
  4105.         break;
  4106.     }
  4107.     }
  4108. }
  4109.  
  4110. /* We only save hardware registers during the hardware frame. Now, when
  4111.  * drawing the frame, we expand the data into a slightly more useful
  4112.  * form. */
  4113. static void pfield_expand_dp_bplcon (void)
  4114. {
  4115.     bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
  4116.     bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12;
  4117.     bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
  4118. #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
  4119.               * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
  4120.     bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
  4121. #else
  4122.     bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
  4123. #endif
  4124.     bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
  4125.     bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
  4126.     plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
  4127.     plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
  4128.     bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
  4129.     bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
  4130. }
  4131.  
  4132. static __inline__ void pfield_draw_line(int lineno, int gfx_ypos, int follow_ypos)
  4133. {
  4134.     int border = 0;
  4135.     int to_screen = 0;
  4136.     int do_double = 0;
  4137.  
  4138.     dp_for_drawing = 0;
  4139.     dip_for_drawing = 0;
  4140.     switch (linestate[lineno]) {
  4141.      case LINE_AS_PREVIOUS:
  4142.      case LINE_REMEMBERED_AS_PREVIOUS:
  4143.     {
  4144.         static int warned = 0;
  4145.         if (!warned)
  4146.         write_log ("Shouldn't get here... this is a bug.\n"), warned++;
  4147.     }
  4148.     line_decisions[lineno].which = -2;
  4149.     return;
  4150.  
  4151.      case LINE_BORDER_PREV:
  4152.     border = 1;
  4153.     dp_for_drawing = line_decisions + lineno - 1;
  4154.     dip_for_drawing = curr_drawinfo + lineno - 1;
  4155.     break;
  4156.  
  4157.      case LINE_BORDER_NEXT:
  4158.     border = 1;
  4159.     dp_for_drawing = line_decisions + lineno + 1;
  4160.     dip_for_drawing = curr_drawinfo + lineno + 1;
  4161.     break;
  4162.  
  4163.      case LINE_DONE_AS_PREVIOUS:
  4164.     line_decisions[lineno].which = -2;
  4165.     /* fall through */
  4166.      case LINE_DONE:
  4167.     return;
  4168.  
  4169.      case LINE_DECIDED_DOUBLE:
  4170.     line_decisions[lineno+1].which = -2;
  4171.     if (follow_ypos != -1) {
  4172.         do_double = 1;
  4173.         linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
  4174.     }
  4175.  
  4176.     /* fall through */
  4177.      default:
  4178.     dip_for_drawing = curr_drawinfo + lineno;
  4179.     dp_for_drawing = line_decisions + lineno;
  4180.     if (dp_for_drawing->which != 1)
  4181.         border = 1;
  4182.     break;
  4183.     }
  4184.  
  4185.     if (!line_changed[lineno] && !frame_redraw_necessary) {
  4186.     /* The case where we can skip redrawing this line. If this line
  4187.      * is supposed to be doubled, and the next line is remembered as
  4188.      * having been doubled, then the next line is done as well. */
  4189.     if (do_double) {
  4190.         if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) {
  4191.         if (gfxvidinfo.linemem == NULL)
  4192.             memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
  4193.         line_decisions[lineno + 1].which = -2;
  4194.         do_flush_line (follow_ypos);
  4195.         }
  4196.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4197.     }
  4198.     linestate[lineno] = LINE_DONE;
  4199.     return;
  4200.     }
  4201.  
  4202.     if (!border) {
  4203.     xlinebuffer = gfxvidinfo.linemem;
  4204.     if (xlinebuffer == NULL)
  4205.         xlinebuffer = row_map[gfx_ypos];
  4206.     xlinebuffer -= linetoscr_x_adjust_bytes;
  4207.     aga_lbufptr = aga_linebuf;
  4208.  
  4209.     pfield_expand_dp_bplcon ();
  4210.  
  4211. #ifdef LORES_HACK
  4212.     if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
  4213.         && dip_for_drawing->nr_color_changes == 0 && !bplham)
  4214.         currprefs.gfx_lores = 2;
  4215. #endif
  4216.     pfield_init_linetoscr ();
  4217.     if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
  4218.         bpldelay1 = bpldelay2 = 0;
  4219.         if (currprefs.gfx_lores)
  4220.         pfield_doline_l (lineno);
  4221.         else
  4222.         pfield_doline_h (lineno);
  4223.         pfield_adjust_delay ();
  4224.     } else {
  4225.         if (currprefs.gfx_lores)
  4226.         pfield_doline_l (lineno);
  4227.         else
  4228.         pfield_doline_h (lineno);
  4229.     }
  4230.  
  4231.     /* Check color0 adjust only if we have color changes - shouldn't happen
  4232.      * otherwise. */
  4233.     adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
  4234.  
  4235.     /* The problem is that we must call decode_ham6() BEFORE we do the
  4236.      * sprites. */
  4237.     if (bplham) {
  4238.         init_ham_decoding(linetoscr_x_adjust);
  4239.         if (dip_for_drawing->nr_color_changes == 0) {
  4240.         /* The easy case: need to do HAM decoding only once for the
  4241.          * full line. */
  4242.         decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
  4243.         } else /* Argh. */ {
  4244.         adjust_color0_for_color_change ();
  4245.         do_color_changes (decode_ham6);
  4246.         adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
  4247.         }
  4248.     }
  4249.  
  4250.     if (dip_for_drawing->nr_sprites != 0) {
  4251.         int spr;
  4252.         walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
  4253.     }
  4254.     if (dip_for_drawing->nr_color_changes == 0) {
  4255.         pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0);
  4256.         do_flush_line (gfx_ypos);
  4257.         linestate[lineno] = LINE_DONE;
  4258.  
  4259.         if (do_double) {
  4260.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4261.         do_flush_line (follow_ypos);
  4262.         }
  4263.     } else {
  4264.         int lastpos = 0, nextpos, i;
  4265.  
  4266.         adjust_color0_for_color_change ();
  4267.         do_color_changes (pfield_do_linetoscr);
  4268.  
  4269.         linestate[lineno] = LINE_DONE;
  4270.         do_flush_line (gfx_ypos);
  4271.         if (do_double) {
  4272.         if (gfxvidinfo.linemem == NULL)
  4273.             memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
  4274.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4275.         line_decisions[lineno + 1].which = -2;
  4276.         do_flush_line (follow_ypos);
  4277.         }
  4278.     }
  4279. #ifdef LORES_HACK
  4280.     if (currprefs.gfx_lores == 2)
  4281.         currprefs.gfx_lores = 0;
  4282. #endif
  4283.     } else {
  4284.     /* Border. */
  4285.     int i, lastpos = 0, nextpos;
  4286.     struct color_change *cc;
  4287.  
  4288.     xlinebuffer = gfxvidinfo.linemem;
  4289.     if (xlinebuffer == NULL)
  4290.         xlinebuffer = row_map[gfx_ypos];
  4291.     xlinebuffer -= linetoscr_x_adjust_bytes;
  4292.  
  4293.     adjust_drawing_colors (dp_for_drawing->ctable, 0);
  4294.     /* Check color0 adjust only if we have color changes - shouldn't happen
  4295.      * otherwise. */
  4296.  
  4297.     if (dip_for_drawing->nr_color_changes == 0) {
  4298.         fill_line ();
  4299.         do_flush_line (gfx_ypos);
  4300.         linestate[lineno] = LINE_DONE;
  4301.         if (do_double) {
  4302.         if (gfxvidinfo.linemem == NULL) {
  4303.             xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
  4304.             fill_line ();
  4305.         }
  4306.         do_flush_line (follow_ypos);
  4307.         linestate[lineno+1] = LINE_DONE_AS_PREVIOUS;
  4308.         }
  4309.         return;
  4310.     }
  4311.  
  4312.     adjust_color0_for_color_change ();
  4313.     do_color_changes (pfield_do_fill_line);
  4314.  
  4315.     do_flush_line (gfx_ypos);
  4316.     linestate[lineno] = LINE_DONE;
  4317.     if (do_double) {
  4318.         if (gfxvidinfo.linemem == NULL)
  4319.         memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
  4320.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4321.         line_decisions[lineno + 1].which = -2;
  4322.         do_flush_line (follow_ypos);
  4323.     }
  4324.     }
  4325. }
  4326.  
  4327. #ifdef SUPPORT_PENGUINS
  4328. static smp_comm_pipe drawing_pipe;
  4329. static uae_sem_t drawing_lock;
  4330.  
  4331. static void *drawing_penguin (void *cruxmedo)
  4332. {
  4333.     int l;
  4334.     fprintf(stderr, "Hello, world!\n");
  4335.  
  4336.     for (;;) {
  4337.     /* Start of a frame. */
  4338.     int k;
  4339.     new_frame:
  4340.     k = read_comm_pipe_int_blocking (&drawing_pipe);
  4341.  
  4342.     switch (k) {
  4343.      case -2:
  4344.         /* Hoopy */
  4345.         break;
  4346.  
  4347.      default:
  4348.         write_log ("Penguin got out of sync.\n");
  4349.         /* what can we do? Try to reduce the damage */
  4350.         for (;;) {
  4351.         k = read_comm_pipe_int_blocking (&drawing_pipe);
  4352.         if (k == -3)
  4353.             break;
  4354.         if (k == -1) {
  4355.             uae_sem_post (&drawing_lock);
  4356.             goto new_frame;
  4357.         }
  4358.         }
  4359.      case -3:
  4360.         UAE_PENGUIN_EXIT;
  4361.         /* Can't happen */
  4362.         return 0;
  4363.     }
  4364.  
  4365.     for (;;) {
  4366.         int i, where;
  4367.         int l = read_comm_pipe_int_blocking (&drawing_pipe);
  4368.         switch (l) {
  4369.          case -1:
  4370.         /* End-of-frame synchronization. */
  4371.         uae_sem_post (&drawing_lock);
  4372.         goto new_frame;
  4373.          case -2:
  4374.         /* customreset called a bit too often. That's harmless. */
  4375.         continue;
  4376.          case -3:
  4377.         write_log ("Penguin got out of sync.\n");
  4378.         UAE_PENGUIN_EXIT;
  4379.         return 0;
  4380.         }
  4381.  
  4382.         /* l is the line that has been finished for drawing. */
  4383.         i = l - thisframe_y_adjust_real;
  4384.         if (i < 0 || i >= max_ypos_thisframe)
  4385.         continue;
  4386.  
  4387.         if (linestate[l] == LINE_UNDECIDED) {
  4388.         fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
  4389.         continue;
  4390.         }
  4391.         if (inhibit_frame != 0)
  4392.         continue;
  4393.         where = amiga2aspect_line_map[i+min_ypos_for_screen];
  4394.         if (where >= gfxvidinfo.height || where == -1)
  4395.         continue;
  4396.  
  4397.         pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
  4398.     }
  4399.     }
  4400. }
  4401.  
  4402. static penguin_id our_penguin;
  4403.  
  4404. static void kill_drawing_penguin (void)
  4405. {
  4406.     /* ??? does libpthread do that for us? */
  4407. }
  4408.  
  4409. #endif
  4410.  
  4411. static int penguins_enabled_thisframe;
  4412.  
  4413. static void init_drawing_frame (void)
  4414. {
  4415.     int i, maxline;
  4416.  
  4417. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  4418.     if(delta_sprite_draw) {
  4419.     void *p1,*p2;
  4420.     int mcc = max_sprite_draw + 200 + delta_sprite_draw;
  4421.     delta_sprite_draw = 0;
  4422.     p1 = realloc(sprite_positions[0], mcc*sizeof(struct sprite_draw));
  4423.     p2 = realloc(sprite_positions[1], mcc*sizeof(struct sprite_draw));
  4424.     if(p1) sprite_positions[0] = p1;
  4425.     if(p2) sprite_positions[1] = p2;
  4426.     if(p1 && p2) {
  4427.         fprintf(stderr,"new max_sprite_draw=%d\n",mcc);
  4428.         max_sprite_draw = mcc;
  4429.     }
  4430.     }
  4431.     if(delta_color_change) {
  4432.     void *p1,*p2;
  4433.     int mcc = max_color_change + 200 + delta_color_change;
  4434.     delta_color_change = 0;
  4435.     p1 = realloc(color_changes[0], mcc*sizeof(struct color_change));
  4436.     p2 = realloc(color_changes[1], mcc*sizeof(struct color_change));
  4437.     if(p1) color_changes[0] = p1;
  4438.     if(p2) color_changes[1] = p2;
  4439.     if(p1 && p2) {
  4440.         fprintf(stderr,"new max_color_change=%d\n",mcc);
  4441.         max_color_change = mcc;
  4442.     }
  4443.     }
  4444.     if(delta_delay_change) {
  4445.     void *p;
  4446.     int mcc = max_delay_change + 200 + delta_delay_change;
  4447.     delta_delay_change = 0;
  4448.     p = realloc(delay_changes, mcc*sizeof(struct delay_change));
  4449.     if(p) {
  4450.         fprintf(stderr,"new max_delay_change=%d\n",mcc);
  4451.         delay_changes = p;
  4452.         max_delay_change = mcc;
  4453.     }
  4454.     }
  4455. #endif
  4456.  
  4457.     if (max_diwstop == 0)
  4458.     max_diwstop = diwlastword;
  4459.     if (min_diwstart > max_diwstop)
  4460.     min_diwstart = 0;
  4461.  
  4462.     if (thisframe_first_drawn_line == -1)
  4463.     thisframe_first_drawn_line = minfirstline;
  4464.     if (thisframe_first_drawn_line > thisframe_last_drawn_line)
  4465.     thisframe_last_drawn_line = thisframe_first_drawn_line;
  4466.  
  4467.     next_color_change = 0;
  4468.     next_delay_change = 0;
  4469.     next_sprite_draw = 0;
  4470.     maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
  4471. #ifdef SMART_UPDATE
  4472.     for (i = 0; i < maxline; i++)
  4473.     linestate[i] = linestate[i] == LINE_DONE_AS_PREVIOUS ? LINE_REMEMBERED_AS_PREVIOUS : LINE_UNDECIDED;
  4474. #else
  4475.     memset (linestate, LINE_UNDECIDED, maxline);
  4476. #endif
  4477.     last_drawn_line = 0;
  4478.     first_drawn_line = 32767;
  4479.  
  4480.     first_block_line = last_block_line = -2;
  4481.     if (currprefs.test_drawing_speed)
  4482.     frame_redraw_necessary = 1;
  4483.     else if (frame_redraw_necessary)
  4484.     frame_redraw_necessary--;
  4485.  
  4486.     next_color_entry = 0;
  4487.     remembered_color_entry = -1;
  4488.     prev_sprite_positions = sprite_positions[current_change_set];
  4489.     curr_sprite_positions = sprite_positions[current_change_set ^ 1];
  4490.     prev_color_changes = color_changes[current_change_set];
  4491.     curr_color_changes = color_changes[current_change_set ^ 1];
  4492.     prev_color_tables = color_tables[current_change_set];
  4493.     curr_color_tables = color_tables[current_change_set ^ 1];
  4494.  
  4495.     prev_drawinfo = line_drawinfo[current_change_set];
  4496.     curr_drawinfo = line_drawinfo[current_change_set ^= 1];
  4497.     drawing_color_matches = -1;
  4498.     color_src_match = color_dest_match = -1;
  4499.  
  4500.     prev_x_adjust = linetoscr_x_adjust;
  4501.     prev_y_adjust = thisframe_y_adjust;
  4502.  
  4503.     if (currprefs.gfx_xcenter) {
  4504.     if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
  4505.         /* Try to center. */
  4506.         linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
  4507.     else
  4508.         linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
  4509.  
  4510.     /* Would the old value be good enough? If so, leave it as it is if we want to
  4511.      * be clever. */
  4512.     if (currprefs.gfx_xcenter == 2) {
  4513.         if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
  4514.         linetoscr_x_adjust = prev_x_adjust;
  4515.     }
  4516.     } else
  4517.     linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
  4518.     if (linetoscr_x_adjust < 0)
  4519.     linetoscr_x_adjust = 0;
  4520.  
  4521.     linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
  4522.  
  4523.     linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
  4524.     if (linetoscr_right_x > max_diwlastword)
  4525.     linetoscr_right_x = max_diwlastword;
  4526.  
  4527.     thisframe_y_adjust = minfirstline;
  4528.     if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
  4529.     if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
  4530.         thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
  4531.     else
  4532.         thisframe_y_adjust = thisframe_first_drawn_line;
  4533.     /* Would the old value be good enough? If so, leave it as it is if we want to
  4534.      * be clever. */
  4535.     if (currprefs.gfx_ycenter == 2) {
  4536.         if (thisframe_y_adjust != prev_y_adjust
  4537.         && prev_y_adjust <= thisframe_first_drawn_line
  4538.         && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
  4539.         thisframe_y_adjust = prev_y_adjust;
  4540.     }
  4541.     /* Make sure the value makes sense */
  4542.     if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
  4543.         thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
  4544.     if (thisframe_y_adjust < minfirstline)
  4545.         thisframe_y_adjust = minfirstline;
  4546.     }
  4547.     thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
  4548.     max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
  4549.  
  4550.     if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
  4551.     frame_redraw_necessary |= (bplcon0 & 4) && currprefs.gfx_linedbl ? 2 : 1;
  4552.  
  4553.     max_diwstop = 0;
  4554.     min_diwstart = 10000;
  4555.     thisframe_first_drawn_line = -1;
  4556.     thisframe_last_drawn_line = -1;
  4557. #ifdef SUPPORT_PENGUINS
  4558.     penguins_enabled_thisframe = 1;
  4559.     /* Tell the other thread that it can now expect data from us. */
  4560.     write_comm_pipe_int (&drawing_pipe, -2, 1);
  4561.     memset (line_drawn, 0, sizeof line_drawn);
  4562. #endif
  4563. }
  4564.  
  4565. static void finish_drawing_frame (void)
  4566. {
  4567.     int i;
  4568.  
  4569. #ifdef SUPPORT_PENGUINS
  4570.     /* Synchronize with other thread, then see whether there's something left for
  4571.      * us to draw. @@@ This is probably a big waste of cycles if the two threads
  4572.      * run at very different speeds - this one could draw stuff as well. */
  4573.     write_comm_pipe_int (&drawing_pipe, -1, 1);
  4574.     uae_sem_wait (&drawing_lock);
  4575. #else
  4576.  
  4577. #ifndef SMART_UPDATE
  4578.     /* @@@ This isn't exactly right yet. FIXME */
  4579.     if (!interlace_seen) {
  4580.     do_flush_screen (first_drawn_line, last_drawn_line);
  4581.     return;
  4582.     }
  4583. #endif
  4584.     for (i = 0; i < max_ypos_thisframe; i++) {
  4585.     int where;
  4586.     int line = i + thisframe_y_adjust_real;
  4587.  
  4588.     if (linestate[line] == LINE_UNDECIDED)
  4589.         break;
  4590.  
  4591.     where = amiga2aspect_line_map[i+min_ypos_for_screen];
  4592.     if (where >= gfxvidinfo.height)
  4593.         break;
  4594.     if (where == -1)
  4595.         continue;
  4596.  
  4597.     pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
  4598.     }
  4599. #endif
  4600.     do_flush_screen (first_drawn_line, last_drawn_line);
  4601. }
  4602.  
  4603. static __inline__ void check_picasso (void)
  4604. {
  4605. #ifdef PICASSO96
  4606.     if (picasso_requested_on == picasso_on)
  4607.     return;
  4608.  
  4609.     picasso_on = picasso_requested_on;
  4610.  
  4611.     if (!picasso_on)
  4612.     clear_inhibit_frame (2);
  4613.     else
  4614.     set_inhibit_frame (2);
  4615.  
  4616.     gfx_set_picasso_state (picasso_on);
  4617.     picasso_enablescreen (picasso_requested_on);
  4618.  
  4619.     notice_screen_contents_lost ();
  4620. #endif
  4621. }
  4622.  
  4623. static void vsync_handler (void)
  4624. {
  4625. #ifdef FRAME_RATE_HACK /* put this here or at the end of the function? */
  4626.     {
  4627.     frame_time_t curr_time = read_processor_time();
  4628.     vsyncmintime += vsynctime;
  4629.     /* @@@ Mathias? How do you think we should do this? */
  4630.     /* If we are too far behind, or we just did a reset, adjust the
  4631.      * needed time. */
  4632.     if ((long int)(curr_time - vsyncmintime) > 0 || did_reset)
  4633.         vsyncmintime = curr_time + vsynctime;
  4634.     did_reset = 0;
  4635.     }
  4636. #endif
  4637.     handle_events ();
  4638.  
  4639.     getjoystate (0, &joy0dir, &joy0button);
  4640.     getjoystate (1, &joy1dir, &joy1button);
  4641.  
  4642.     INTREQ(0x8020);
  4643.     if (bplcon0 & 4)
  4644.     lof ^= 0x8000;
  4645.  
  4646.     if (quit_program < 0) {
  4647.     quit_program = -quit_program;
  4648.     set_inhibit_frame (1);
  4649.     regs.spcflags |= SPCFLAG_BRK;
  4650.     if (framecnt == 0)
  4651.         finish_drawing_frame ();
  4652.     filesys_prepare_reset ();
  4653. #ifdef SUPPORT_PENGUINS
  4654.     if (quit_program == 1)
  4655.         /* Stop eating herring */
  4656.         write_comm_pipe_int (&drawing_pipe, -3, 1);
  4657. #endif
  4658.     return;
  4659.     }
  4660.  
  4661.     last_redraw_point++;
  4662.     if (lof_changed || !interlace_seen || last_redraw_point >= 2 || lof) {
  4663.     static int cnt = 0;
  4664.  
  4665.     if (framecnt == 0)
  4666.         finish_drawing_frame ();
  4667.     count_frame ();
  4668.     last_redraw_point = 0;
  4669.  
  4670.     check_picasso ();
  4671.  
  4672.     uae_sem_wait (&ihf_sem);
  4673.     if (inhibit_frame != 0)
  4674.         framecnt = 1;
  4675.     if (frame_do_semup)
  4676.         uae_sem_post (&frame_sem);
  4677.     frame_do_semup = 0;
  4678.     uae_sem_post (&ihf_sem);
  4679.  
  4680.     if (cnt == 0) {
  4681.         /* resolution_check_change (); */
  4682.         DISK_check_change ();
  4683.         cnt = 5;
  4684.     }
  4685.     cnt--;
  4686.     if (framecnt == 0)
  4687.         init_drawing_frame ();
  4688.     }
  4689.  
  4690.     lof_changed = 0;
  4691.     interlace_seen = 0;
  4692.     COPJMP1(0);
  4693.  
  4694.     init_hardware_frame();
  4695. #ifdef HAVE_GETTIMEOFDAY
  4696.     {
  4697.     struct timeval tv;
  4698.     unsigned long int newtime;
  4699.  
  4700.     gettimeofday(&tv,NULL);
  4701.     newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
  4702.  
  4703.     if (!bogusframe) {
  4704.         frametime += newtime - msecs;
  4705.         timeframes++;
  4706.     }
  4707.     msecs = newtime;
  4708.     bogusframe = 0;
  4709.     }
  4710. #endif
  4711.     if (ievent_alive > 0)
  4712.     ievent_alive--;
  4713.     CIA_vsync_handler();
  4714. }
  4715.  
  4716. static void hsync_handler(void)
  4717. {
  4718.     int lineno = next_lineno;
  4719.     int lineisdouble = 0;
  4720.     int line_was_doubled = 0;
  4721.  
  4722.     finish_decisions ();
  4723.     do_modulos ();
  4724.  
  4725.     if (framecnt == 0) {
  4726.     switch (nln_how) {
  4727.      case 0:
  4728.         linestate[lineno] = LINE_DECIDED;
  4729.         break;
  4730.      case 1:
  4731.         linestate[lineno] = LINE_DECIDED_DOUBLE;
  4732.         if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS)
  4733.         linestate[lineno+1] = LINE_AS_PREVIOUS;
  4734.         break;
  4735.      case 2:
  4736.         if (linestate[lineno-1] == LINE_UNDECIDED)
  4737.         linestate[lineno-1] = LINE_BORDER_NEXT;
  4738.         linestate[lineno] = LINE_DECIDED;
  4739.         break;
  4740.      case 3:
  4741.         linestate[lineno] = LINE_DECIDED;
  4742.         if (linestate[lineno+1] == LINE_UNDECIDED
  4743.         || linestate[lineno+1] == LINE_REMEMBERED_AS_PREVIOUS
  4744.         || linestate[lineno+1] == LINE_AS_PREVIOUS)
  4745.         linestate[lineno+1] = LINE_BORDER_PREV;
  4746.         break;
  4747.     }
  4748.     }
  4749.  
  4750.     eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles;
  4751.     eventtab[ev_hsync].oldcycles = cycles;
  4752.     CIA_hsync_handler();
  4753.  
  4754.     if (currprefs.produce_sound > 0) {
  4755.     int nr;
  4756.     /* Sound data is fetched at the beginning of each line */
  4757.     for (nr = 0; nr < 4; nr++) {
  4758.         struct audio_channel_data *cdp = audio_channel + nr;
  4759.  
  4760.         if (cdp->data_written == 2) {
  4761.         cdp->data_written = 0;
  4762.         cdp->nextdat = chipmem_bank.wget(cdp->pt);
  4763.         cdp->pt += 2;
  4764.         if (cdp->state == 2 || cdp->state == 3) {
  4765.             if (cdp->wlen == 1) {
  4766.             cdp->pt = cdp->lc;
  4767.             cdp->wlen = cdp->len;
  4768.             cdp->intreq2 = 1;
  4769.             } else
  4770.             cdp->wlen--;
  4771.         }
  4772.         }
  4773.     }
  4774.     }
  4775. #ifdef SUPPORT_PENGUINS
  4776.     if (framecnt == 0 && penguins_enabled_thisframe) {
  4777.     write_comm_pipe_int (&drawing_pipe, next_lineno, 0);
  4778.     }
  4779. #endif
  4780. #ifndef SMART_UPDATE
  4781.     {
  4782.     int i, where;
  4783.     /* l is the line that has been finished for drawing. */
  4784.     i = next_lineno - thisframe_y_adjust_real;
  4785.     if (i >= 0 && i < max_ypos_thisframe) {
  4786.         where = amiga2aspect_line_map[i+min_ypos_for_screen];
  4787.         if (where < gfxvidinfo.height && where != -1)
  4788.         pfield_draw_line (next_lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
  4789.     }
  4790.     }
  4791. #endif
  4792.     if (++vpos == (maxvpos + (lof != 0))) {
  4793.     vpos = 0;
  4794.     vsync_handler();
  4795.     }
  4796.  
  4797.     is_lastline = vpos + 1 == maxvpos + (lof != 0);
  4798.  
  4799.     if ((bplcon0 & 4) && currprefs.gfx_linedbl) {
  4800.     interlace_seen = 1, penguins_enabled_thisframe = 0;
  4801.     }
  4802.  
  4803.     if (framecnt == 0) {
  4804.     lineno = vpos;
  4805.     nln_how = 0;
  4806.     if (currprefs.gfx_linedbl) {
  4807.         lineno *= 2;
  4808.         nln_how = 1;
  4809.         if (bplcon0 & 4) {
  4810.         if (!lof) {
  4811.             lineno++;
  4812.             nln_how = 2;
  4813.         } else {
  4814.             nln_how = 3;
  4815.         }
  4816.         }
  4817.     }
  4818.     next_lineno = lineno;
  4819.     reset_decisions ();
  4820.     }
  4821.     if (uae_int_requested) {
  4822.     set_uae_int_flag ();
  4823.     INTREQ (0xA000);
  4824.     }
  4825. }
  4826.  
  4827. static void init_eventtab (void)
  4828. {
  4829.     int i;
  4830.  
  4831.     for(i = 0; i < ev_max; i++) {
  4832.     eventtab[i].active = 0;
  4833.     eventtab[i].oldcycles = 0;
  4834.     }
  4835.     copper_active = 0;
  4836.     eventtab[ev_cia].handler = CIA_handler;
  4837.     eventtab[ev_copper].handler = currprefs.copper_pos < 0 ? do_copper : do_copper_cheat;
  4838.     eventtab[ev_hsync].handler = hsync_handler;
  4839.     eventtab[ev_hsync].evtime = maxhpos + cycles;
  4840.     eventtab[ev_hsync].active = 1;
  4841.  
  4842.     eventtab[ev_blitter].handler = blitter_handler;
  4843.     eventtab[ev_blitter].active = 0;
  4844.     eventtab[ev_diskblk].handler = diskblk_handler;
  4845.     eventtab[ev_diskblk].active = 0;
  4846.     eventtab[ev_diskindex].handler = diskindex_handler;
  4847.     eventtab[ev_diskindex].active = 0;
  4848. #ifndef DONT_WANT_SOUND
  4849.     eventtab[ev_aud0].handler = aud0_handler;
  4850.     eventtab[ev_aud0].active = 0;
  4851.     eventtab[ev_aud1].handler = aud1_handler;
  4852.     eventtab[ev_aud1].active = 0;
  4853.     eventtab[ev_aud2].handler = aud2_handler;
  4854.     eventtab[ev_aud2].active = 0;
  4855.     eventtab[ev_aud3].handler = aud3_handler;
  4856.     eventtab[ev_aud3].active = 0;
  4857.     if (sound_available && currprefs.produce_sound >= 2) {
  4858.     eventtab[ev_sample].active = 1;
  4859.     eventtab[ev_sample].evtime = sample_evtime;
  4860.     } else {
  4861.     eventtab[ev_sample].active = 0;
  4862.     }
  4863. #endif
  4864.     events_schedule ();
  4865. }
  4866.  
  4867. void customreset(void)
  4868. {
  4869.     int i, maxl;
  4870.     double native_lines_per_amiga_line;
  4871. #ifdef HAVE_GETTIMEOFDAY
  4872.     struct timeval tv;
  4873. #endif
  4874.  
  4875.     for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++)
  4876.     current_colors.color_regs[i] = -1;
  4877.  
  4878. #ifdef FRAME_RATE_HACK
  4879.     did_reset = 1;
  4880.     vsyncmintime = read_processor_time() + vsynctime;
  4881. #endif
  4882.     inhibit_frame = 0;
  4883.     frame_do_semup = 0;
  4884.     uae_sem_init (&frame_sem, 0, 0);
  4885.     uae_sem_init (&gui_sem, 0, 1);
  4886.     uae_sem_init (&ihf_sem, 0, 1);
  4887.     expamem_reset ();
  4888.     filesys_reset ();
  4889.     CIA_reset ();
  4890. #ifdef PICASSO96
  4891.     InitPicasso96 ();
  4892.     picasso_on = 0;
  4893.     picasso_requested_on = 0;
  4894.     gfx_set_picasso_state (0);
  4895. #endif
  4896.     cycles = 0;
  4897.     regs.spcflags &= SPCFLAG_BRK;
  4898.  
  4899.     lores_factor = currprefs.gfx_lores ? 1 : 2;
  4900.     lores_shift = currprefs.gfx_lores ? 0 : 1;
  4901.     sprite_width = currprefs.gfx_lores ? 16 : 32;
  4902.  
  4903.     vpos = 0;
  4904.     is_lastline = 0;
  4905.     lof = 0;
  4906.     max_diwstop = 0;
  4907.  
  4908.     if (needmousehack()) {
  4909. #if 0
  4910.     if (mousestate != follow_mouse) setfollow();
  4911. #else
  4912.     if (mousestate != dont_care_mouse) setdontcare();
  4913. #endif
  4914.     } else {
  4915.     mousestate = normal_mouse;
  4916.     }
  4917.     ievent_alive = 0;
  4918.  
  4919.     clx_sprmask = 0xFF;
  4920.     clxdat = 0;
  4921.  
  4922.     memset(sprarmed, 0, sizeof sprarmed);
  4923.     nr_armed = 0;
  4924.  
  4925.     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
  4926.     for (i = 0; i < (maxvpos+1)*2 + 1; i++) {
  4927.     linestate[i] = LINE_UNDECIDED;
  4928.     }
  4929.     xlinebuffer = gfxvidinfo.bufmem;
  4930.  
  4931.     dmacon = intena = 0;
  4932.     bltstate = BLT_done;
  4933.     copstate = COP_stop;
  4934.     diwstate = DIW_waiting_start;
  4935.     hdiwstate = DIW_waiting_start;
  4936.     copcon = 0;
  4937.     dskdmaen = 0;
  4938.     cycles = 0;
  4939.  
  4940.     memset(audio_channel, 0, sizeof audio_channel);
  4941.     audio_channel[0].per = 65535;
  4942.     audio_channel[1].per = 65535;
  4943.     audio_channel[2].per = 65535;
  4944.     audio_channel[3].per = 65535;
  4945.  
  4946.     bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
  4947.     bplcon3 = 0xC00;
  4948.  
  4949.     init_eventtab ();
  4950.  
  4951.     if (native2amiga_line_map)
  4952.     free (native2amiga_line_map);
  4953.     if (amiga2aspect_line_map)
  4954.     free (amiga2aspect_line_map);
  4955.  
  4956.     /* At least for this array the +1 is necessary. */
  4957.     amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
  4958.     native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
  4959.  
  4960.     if (currprefs.gfx_correct_aspect)
  4961.     native_lines_per_amiga_line = ((double)gfxvidinfo.height
  4962.                        * (currprefs.gfx_lores ? 320 : 640)
  4963.                        / (currprefs.gfx_linedbl ? 512 : 256)
  4964.                        / gfxvidinfo.width);
  4965.     else
  4966.     native_lines_per_amiga_line = 1;
  4967.  
  4968.     maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
  4969.     min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
  4970.     max_drawn_amiga_line = -1;
  4971.     for (i = 0; i < maxl; i++) {
  4972.     int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
  4973.     if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
  4974.         max_drawn_amiga_line = i-min_ypos_for_screen;
  4975.     if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
  4976.         v = -1;
  4977.     amiga2aspect_line_map[i] = v;
  4978.     }
  4979.     if (currprefs.gfx_linedbl)
  4980.     max_drawn_amiga_line >>= 1;
  4981.  
  4982.     if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
  4983.     extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
  4984.     if (extra_y_adjust < 0)
  4985.         extra_y_adjust = 0;
  4986.     }
  4987.  
  4988.     for (i = 0; i < gfxvidinfo.height; i++)
  4989.     native2amiga_line_map[i] = -1;
  4990.  
  4991.     if (native_lines_per_amiga_line < 1) {
  4992.     /* Must omit drawing some lines. */
  4993.     for (i = maxl-1; i > min_ypos_for_screen; i--) {
  4994.         if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
  4995.         if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
  4996.             /* If only the first line of a line pair would be omitted,
  4997.              * omit the second one instead to avoid problems with line
  4998.              * doubling. */
  4999.             amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
  5000.             amiga2aspect_line_map[i+1] = -1;
  5001.         } else
  5002.             amiga2aspect_line_map[i] = -1;
  5003.         }
  5004.     }
  5005.     }
  5006.  
  5007.     for (i = maxl-1; i >= min_ypos_for_screen; i--) {
  5008.     int j;
  5009.     if (amiga2aspect_line_map[i] == -1)
  5010.         continue;
  5011.     for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
  5012.         native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
  5013.     }
  5014.  
  5015.     if (line_drawn == 0)
  5016.     line_drawn = (char *)malloc (gfxvidinfo.height);
  5017.     init_row_map();
  5018.  
  5019.     init_sprites ();
  5020.  
  5021.     init_hardware_frame ();
  5022.     init_drawing_frame ();
  5023.     last_redraw_point = 0;
  5024.     reset_decisions ();
  5025.  
  5026. #ifdef HAVE_GETTIMEOFDAY
  5027.     gettimeofday(&tv,NULL);
  5028.     seconds_base = tv.tv_sec;
  5029.     bogusframe = 1;
  5030. #endif
  5031. }
  5032.  
  5033. void dumpcustom(void)
  5034. {
  5035.     int i;
  5036.     fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
  5037.        intena, intreq, vpos, current_hpos());
  5038.     if (timeframes) {
  5039.     fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n",
  5040.            frametime/timeframes, timeframes, frametime);
  5041.     }
  5042.     /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]);  blitter debug */
  5043. }
  5044.  
  5045. int intlev(void)
  5046. {
  5047.     uae_u16 imask = intreq & intena;
  5048.     if (imask && (intena & 0x4000)){
  5049.     if (imask & 0x2000) return 6;
  5050.     if (imask & 0x1800) return 5;
  5051.     if (imask & 0x0780) return 4;
  5052.     if (imask & 0x0070) return 3;
  5053.     if (imask & 0x0008) return 2;
  5054.     if (imask & 0x0007) return 1;
  5055.     }
  5056.     return -1;
  5057. }
  5058.  
  5059. void custom_init(void)
  5060. {
  5061.     int num;
  5062.  
  5063. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  5064.     for(num=0;num<2;++num) {
  5065.        sprite_positions[num] = xmalloc(max_sprite_draw * sizeof(struct sprite_draw));
  5066.        color_changes[num] = xmalloc(max_color_change * sizeof(struct color_change));
  5067.     }
  5068.     delay_changes = xmalloc(max_delay_change * sizeof(struct delay_change));
  5069. #endif
  5070.  
  5071.     if (needmousehack())
  5072.     setfollow();
  5073.     init_regchanges ();
  5074.     init_decisions ();
  5075.  
  5076.     /* For now, the AGA stuff is broken in the dual playfield case. We encode
  5077.      * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
  5078.      * playfield rendering easy, the lookup tables contain are made linear for
  5079.      * values >= 128. That only works for OCS/ECS, though. */
  5080.  
  5081.     for (num = 0; num < 256; num++) {
  5082.     int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8);
  5083.     int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8);
  5084.     dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
  5085.     dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
  5086.     if (plane2 > 0) plane2 += 8;
  5087.     dblpf_ind1[num] = num >= 128 ? num & 0x7F : (plane1 == 0 ? plane2 : plane1);
  5088.     dblpf_ind2[num] = num >= 128 ? num & 0x7F : (plane2 == 0 ? plane1 : plane2);
  5089.  
  5090.     lots_of_twos[num] = num == 0 ? 0 : 2;
  5091.     linear_map_256[num] = num;
  5092.     }
  5093.     build_blitfilltable();
  5094.     gen_pfield_tables();
  5095.     native2amiga_line_map = 0;
  5096.     amiga2aspect_line_map = 0;
  5097.     line_drawn = 0;
  5098.  
  5099. #ifdef SUPPORT_PENGUINS
  5100.     init_comm_pipe (&drawing_pipe, 800, 5);
  5101.     uae_sem_init (&drawing_lock, 0, 0);
  5102.     start_penguin (drawing_penguin, 0, &our_penguin);
  5103.     /*atexit(kill_drawing_penguin);*/
  5104. #endif
  5105. }
  5106.  
  5107. /* Custom chip memory bank */
  5108.  
  5109. static uae_u32 custom_lget(uaecptr) REGPARAM;
  5110. static uae_u32 custom_wget(uaecptr) REGPARAM;
  5111. static uae_u32 custom_bget(uaecptr) REGPARAM;
  5112. static void  custom_lput(uaecptr, uae_u32) REGPARAM;
  5113. static void  custom_wput(uaecptr, uae_u32) REGPARAM;
  5114. static void  custom_bput(uaecptr, uae_u32) REGPARAM;
  5115.  
  5116. addrbank custom_bank = {
  5117.     custom_lget, custom_wget, custom_bget,
  5118.     custom_lput, custom_wput, custom_bput,
  5119.     default_xlate, default_check
  5120. };
  5121.  
  5122. uae_u32 REGPARAM2 custom_wget(uaecptr addr)
  5123. {
  5124.     switch(addr & 0x1FE) {
  5125.      case 0x002: return DMACONR();
  5126.      case 0x004: return VPOSR();
  5127.      case 0x006: return VHPOSR();
  5128.  
  5129.      case 0x008: return DSKDATR();
  5130.  
  5131.      case 0x00A: return JOY0DAT();
  5132.      case 0x00C: return JOY1DAT();
  5133.      case 0x00E: return CLXDAT();
  5134.      case 0x010: return ADKCONR();
  5135.  
  5136.      case 0x012: return POT0DAT();
  5137.      case 0x016: return POTGOR();
  5138.      case 0x018: return SERDATR();
  5139.      case 0x01A: return DSKBYTR();
  5140.      case 0x01C: return INTENAR();
  5141.      case 0x01E: return INTREQR();
  5142. #if AGA_CHIPSET == 1
  5143.      case 0x07C: return 0xF8;
  5144. #elif defined ECS_DENISE
  5145.      case 0x07C: return 0xFC;
  5146. #endif
  5147.      default:
  5148.     custom_wput(addr,0);
  5149.     return 0xffff;
  5150.     }
  5151. }
  5152.  
  5153. uae_u32 REGPARAM2 custom_bget(uaecptr addr)
  5154. {
  5155.     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
  5156. }
  5157.  
  5158. uae_u32 REGPARAM2 custom_lget(uaecptr addr)
  5159. {
  5160.     return ((uae_u32)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
  5161. }
  5162.  
  5163. void REGPARAM2 custom_wput(uaecptr addr, uae_u32 value)
  5164. {
  5165.     addr &= 0x1FE;
  5166.     cregs[addr>>1] = value;
  5167.     switch(addr) {
  5168.      case 0x020: DSKPTH(value); break;
  5169.      case 0x022: DSKPTL(value); break;
  5170.      case 0x024: DSKLEN(value); break;
  5171.      case 0x026: DSKDAT(value); break;
  5172.  
  5173.      case 0x02A: VPOSW(value); break;
  5174.      case 0x2E:  COPCON(value); break;
  5175.      case 0x030: SERDAT(value); break;
  5176.      case 0x032: SERPER(value); break;
  5177.      case 0x34: POTGO(value); break;
  5178.      case 0x040: BLTCON0(value); break;
  5179.      case 0x042: BLTCON1(value); break;
  5180.  
  5181.      case 0x044: BLTAFWM(value); break;
  5182.      case 0x046: BLTALWM(value); break;
  5183.  
  5184.      case 0x050: BLTAPTH(value); break;
  5185.      case 0x052: BLTAPTL(value); break;
  5186.      case 0x04C: BLTBPTH(value); break;
  5187.      case 0x04E: BLTBPTL(value); break;
  5188.      case 0x048: BLTCPTH(value); break;
  5189.      case 0x04A: BLTCPTL(value); break;
  5190.      case 0x054: BLTDPTH(value); break;
  5191.      case 0x056: BLTDPTL(value); break;
  5192.  
  5193.      case 0x058: BLTSIZE(value); break;
  5194.  
  5195.      case 0x064: BLTAMOD(value); break;
  5196.      case 0x062: BLTBMOD(value); break;
  5197.      case 0x060: BLTCMOD(value); break;
  5198.      case 0x066: BLTDMOD(value); break;
  5199.  
  5200.      case 0x070: BLTCDAT(value); break;
  5201.      case 0x072: BLTBDAT(value); break;
  5202.      case 0x074: BLTADAT(value); break;
  5203.  
  5204.      case 0x07E: DSKSYNC(value); break;
  5205.  
  5206.      case 0x080: COP1LCH(value); break;
  5207.      case 0x082: COP1LCL(value); break;
  5208.      case 0x084: COP2LCH(value); break;
  5209.      case 0x086: COP2LCL(value); break;
  5210.  
  5211.      case 0x088: COPJMP1(value); break;
  5212.      case 0x08A: COPJMP2(value); break;
  5213.  
  5214.      case 0x08E: DIWSTRT(value); break;
  5215.      case 0x090: DIWSTOP(value); break;
  5216.      case 0x092: DDFSTRT(value); break;
  5217.      case 0x094: DDFSTOP(value); break;
  5218.  
  5219.      case 0x096: DMACON(value); break;
  5220.      case 0x098: CLXCON(value); break;
  5221.      case 0x09A: INTENA(value); break;
  5222.      case 0x09C: INTREQ(value); break;
  5223.      case 0x09E: ADKCON(value); break;
  5224.  
  5225.      case 0x0A0: AUDxLCH(0, value); break;
  5226.      case 0x0A2: AUDxLCL(0, value); break;
  5227.      case 0x0A4: AUDxLEN(0, value); break;
  5228.      case 0x0A6: AUDxPER(0, value); break;
  5229.      case 0x0A8: AUDxVOL(0, value); break;
  5230.      case 0x0AA: AUDxDAT(0, value); break;
  5231.  
  5232.      case 0x0B0: AUDxLCH(1, value); break;
  5233.      case 0x0B2: AUDxLCL(1, value); break;
  5234.      case 0x0B4: AUDxLEN(1, value); break;
  5235.      case 0x0B6: AUDxPER(1, value); break;
  5236.      case 0x0B8: AUDxVOL(1, value); break;
  5237.      case 0x0BA: AUDxDAT(1, value); break;
  5238.  
  5239.      case 0x0C0: AUDxLCH(2, value); break;
  5240.      case 0x0C2: AUDxLCL(2, value); break;
  5241.      case 0x0C4: AUDxLEN(2, value); break;
  5242.      case 0x0C6: AUDxPER(2, value); break;
  5243.      case 0x0C8: AUDxVOL(2, value); break;
  5244.      case 0x0CA: AUDxDAT(2, value); break;
  5245.  
  5246.      case 0x0D0: AUDxLCH(3, value); break;
  5247.      case 0x0D2: AUDxLCL(3, value); break;
  5248.      case 0x0D4: AUDxLEN(3, value); break;
  5249.      case 0x0D6: AUDxPER(3, value); break;
  5250.      case 0x0D8: AUDxVOL(3, value); break;
  5251.      case 0x0DA: AUDxDAT(3, value); break;
  5252.  
  5253.      case 0x0E0: BPLPTH(value, 0); break;
  5254.      case 0x0E2: BPLPTL(value, 0); break;
  5255.      case 0x0E4: BPLPTH(value, 1); break;
  5256.      case 0x0E6: BPLPTL(value, 1); break;
  5257.      case 0x0E8: BPLPTH(value, 2); break;
  5258.      case 0x0EA: BPLPTL(value, 2); break;
  5259.      case 0x0EC: BPLPTH(value, 3); break;
  5260.      case 0x0EE: BPLPTL(value, 3); break;
  5261.      case 0x0F0: BPLPTH(value, 4); break;
  5262.      case 0x0F2: BPLPTL(value, 4); break;
  5263.      case 0x0F4: BPLPTH(value, 5); break;
  5264.      case 0x0F6: BPLPTL(value, 5); break;
  5265.  
  5266.      case 0x100: BPLCON0(value); break;
  5267.      case 0x102: BPLCON1(value); break;
  5268.      case 0x104: BPLCON2(value); break;
  5269.      case 0x106: BPLCON3(value); break;
  5270.  
  5271.      case 0x108: BPL1MOD(value); break;
  5272.      case 0x10A: BPL2MOD(value); break;
  5273.  
  5274.      case 0x110: BPL1DAT(value); break;
  5275.      case 0x112: BPL2DAT(value); break;
  5276.      case 0x114: BPL3DAT(value); break;
  5277.      case 0x116: BPL4DAT(value); break;
  5278.      case 0x118: BPL5DAT(value); break;
  5279.      case 0x11A: BPL6DAT(value); break;
  5280.  
  5281.      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
  5282.      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
  5283.      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
  5284.      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
  5285.      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
  5286.      case 0x1BC: case 0x1BE:
  5287.     COLOR(value & 0xFFF, (addr & 0x3E) / 2);
  5288.     break;
  5289.      case 0x120: case 0x124: case 0x128: case 0x12C:
  5290.      case 0x130: case 0x134: case 0x138: case 0x13C:
  5291.     SPRxPTH(value, (addr - 0x120) / 4);
  5292.     break;
  5293.      case 0x122: case 0x126: case 0x12A: case 0x12E:
  5294.      case 0x132: case 0x136: case 0x13A: case 0x13E:
  5295.     SPRxPTL(value, (addr - 0x122) / 4);
  5296.     break;
  5297.      case 0x140: case 0x148: case 0x150: case 0x158:
  5298.      case 0x160: case 0x168: case 0x170: case 0x178:
  5299.     SPRxPOS(value, (addr - 0x140) / 8);
  5300.     break;
  5301.      case 0x142: case 0x14A: case 0x152: case 0x15A:
  5302.      case 0x162: case 0x16A: case 0x172: case 0x17A:
  5303.     SPRxCTL(value, (addr - 0x142) / 8);
  5304.     break;
  5305.      case 0x144: case 0x14C: case 0x154: case 0x15C:
  5306.      case 0x164: case 0x16C: case 0x174: case 0x17C:
  5307.     SPRxDATA(value, (addr - 0x144) / 8);
  5308.     break;
  5309.      case 0x146: case 0x14E: case 0x156: case 0x15E:
  5310.      case 0x166: case 0x16E: case 0x176: case 0x17E:
  5311.     SPRxDATB(value, (addr - 0x146) / 8);
  5312.     break;
  5313.  
  5314.      case 0x36: JOYTEST(value); break;
  5315. #if defined(ECS_AGNUS) || (AGA_CHIPSET == 1)
  5316.      case 0x5A: BLTCON0L(value); break;
  5317.      case 0x5C: BLTSIZV(value); break;
  5318.      case 0x5E: BLTSIZH(value); break;
  5319. #endif
  5320. #if AGA_CHIPSET == 1
  5321.      case 0x10C: BPLCON4(value); break;
  5322.      case 0x1FC: fmode = value; break;
  5323. #endif
  5324.     }
  5325. }
  5326.  
  5327. void REGPARAM2 custom_bput(uaecptr addr, uae_u32 value)
  5328. {
  5329.     static int warned = 0;
  5330.     /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
  5331.     uae_u16 rval = (value << 8) | (value & 0xFF);
  5332.     custom_wput(addr, rval);
  5333.     if (!warned)
  5334.     write_log ("Byte put to custom register.\n"), warned++;
  5335. }
  5336.  
  5337. void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
  5338. {
  5339.     custom_wput(addr & 0xfffe, value >> 16);
  5340.     custom_wput((addr+2) & 0xfffe, (uae_u16)value);
  5341. }
  5342.